Tor  0.4.7.0-alpha-dev
control_auth.c
Go to the documentation of this file.
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2  * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
4 
5 /**
6  * \file control_auth.c
7  * \brief Authentication for Tor's control-socket interface.
8  **/
9 
10 #include "core/or/or.h"
11 #include "app/config/config.h"
21 #include "lib/encoding/confline.h"
22 #include "lib/encoding/kvline.h"
23 #include "lib/encoding/qstring.h"
24 
26 
27 /** If we're using cookie-type authentication, how long should our cookies be?
28  */
29 #define AUTHENTICATION_COOKIE_LEN 32
30 
31 /** If true, we've set authentication_cookie to a secret code and
32  * stored it to disk. */
34 /** If authentication_cookie_is_set, a secret cookie that we've stored to disk
35  * and which we're using to authenticate controllers. (If the controller can
36  * read it off disk, it has permission to connect.) */
37 static uint8_t *authentication_cookie = NULL;
38 
39 #define SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT \
40  "Tor safe cookie authentication server-to-controller hash"
41 #define SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT \
42  "Tor safe cookie authentication controller-to-server hash"
43 #define SAFECOOKIE_SERVER_NONCE_LEN DIGEST256_LEN
44 
45 /** Helper: Return a newly allocated string containing a path to the
46  * file where we store our authentication cookie. */
47 char *
49 {
50  const or_options_t *options = get_options();
51  if (options->CookieAuthFile && strlen(options->CookieAuthFile)) {
52  return tor_strdup(options->CookieAuthFile);
53  } else {
54  return get_datadir_fname("control_auth_cookie");
55  }
56 }
57 
58 /* Initialize the cookie-based authentication system of the
59  * ControlPort. If <b>enabled</b> is 0, then disable the cookie
60  * authentication system. */
61 int
62 init_control_cookie_authentication(int enabled)
63 {
64  char *fname = NULL;
65  int retval;
66 
67  if (!enabled) {
69  return 0;
70  }
71 
73  retval = init_cookie_authentication(fname, "", /* no header */
75  get_options()->CookieAuthFileGroupReadable,
78  tor_free(fname);
79  return retval;
80 }
81 
82 /** Decode the hashed, base64'd passwords stored in <b>passwords</b>.
83  * Return a smartlist of acceptable passwords (unterminated strings of
84  * length S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on
85  * failure.
86  */
89 {
90  char decoded[64];
91  config_line_t *cl;
92  smartlist_t *sl = smartlist_new();
93 
94  tor_assert(passwords);
95 
96  for (cl = passwords; cl; cl = cl->next) {
97  const char *hashed = cl->value;
98 
99  if (!strcmpstart(hashed, "16:")) {
100  if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))
102  || strlen(hashed+3) != (S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)*2) {
103  goto err;
104  }
105  } else {
106  if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
108  goto err;
109  }
110  }
111  smartlist_add(sl,
112  tor_memdup(decoded, S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN));
113  }
114 
115  return sl;
116 
117  err:
118  SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
119  smartlist_free(sl);
120  return NULL;
121 }
122 
123 const control_cmd_syntax_t authchallenge_syntax = {
124  .min_args = 1,
125  .max_args = 1,
126  .accept_keywords=true,
127  .kvline_flags=KV_OMIT_KEYS|KV_QUOTED_QSTRING,
128  .store_raw_body=true
129 };
130 
131 /** Called when we get an AUTHCHALLENGE command. */
132 int
134  const control_cmd_args_t *args)
135 {
136  char *client_nonce;
137  size_t client_nonce_len;
138  char server_hash[DIGEST256_LEN];
139  char server_hash_encoded[HEX_DIGEST256_LEN+1];
140  char server_nonce[SAFECOOKIE_SERVER_NONCE_LEN];
141  char server_nonce_encoded[(2*SAFECOOKIE_SERVER_NONCE_LEN) + 1];
142 
143  if (strcasecmp(smartlist_get(args->args, 0), "SAFECOOKIE")) {
144  control_write_endreply(conn, 513,
145  "AUTHCHALLENGE only supports SAFECOOKIE "
146  "authentication");
147  goto fail;
148  }
150  control_write_endreply(conn, 515, "Cookie authentication is disabled");
151  goto fail;
152  }
153  if (args->kwargs == NULL || args->kwargs->next != NULL) {
154  control_write_endreply(conn, 512,
155  "Wrong number of arguments for AUTHCHALLENGE");
156  goto fail;
157  }
158  if (strcmp(args->kwargs->key, "")) {
159  control_write_endreply(conn, 512,
160  "AUTHCHALLENGE does not accept keyword "
161  "arguments.");
162  goto fail;
163  }
164 
165  bool contains_quote = strchr(args->raw_body, '\"');
166  if (contains_quote) {
167  /* The nonce was quoted */
168  client_nonce = tor_strdup(args->kwargs->value);
169  client_nonce_len = strlen(client_nonce);
170  } else {
171  /* The nonce was should be in hex. */
172  const char *hex_nonce = args->kwargs->value;
173  client_nonce_len = strlen(hex_nonce) / 2;
174  client_nonce = tor_malloc(client_nonce_len);
175  if (base16_decode(client_nonce, client_nonce_len, hex_nonce,
176  strlen(hex_nonce)) != (int)client_nonce_len) {
177  control_write_endreply(conn, 513, "Invalid base16 client nonce");
178  tor_free(client_nonce);
179  goto fail;
180  }
181  }
182 
183  crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
184 
185  /* Now compute and send the server-to-controller response, and the
186  * server's nonce. */
188 
189  {
190  size_t tmp_len = (AUTHENTICATION_COOKIE_LEN +
191  client_nonce_len +
192  SAFECOOKIE_SERVER_NONCE_LEN);
193  char *tmp = tor_malloc_zero(tmp_len);
194  char *client_hash = tor_malloc_zero(DIGEST256_LEN);
196  memcpy(tmp + AUTHENTICATION_COOKIE_LEN, client_nonce, client_nonce_len);
197  memcpy(tmp + AUTHENTICATION_COOKIE_LEN + client_nonce_len,
198  server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
199 
200  crypto_hmac_sha256(server_hash,
201  SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
202  strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
203  tmp,
204  tmp_len);
205 
206  crypto_hmac_sha256(client_hash,
207  SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
208  strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
209  tmp,
210  tmp_len);
211 
212  conn->safecookie_client_hash = client_hash;
213 
214  tor_free(tmp);
215  }
216 
217  base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
218  server_hash, sizeof(server_hash));
219  base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
220  server_nonce, sizeof(server_nonce));
221 
222  control_printf_endreply(conn, 250,
223  "AUTHCHALLENGE SERVERHASH=%s SERVERNONCE=%s",
224  server_hash_encoded,
225  server_nonce_encoded);
226 
227  tor_free(client_nonce);
228  return 0;
229  fail:
230  connection_mark_for_close(TO_CONN(conn));
231  return -1;
232 }
233 
234 const control_cmd_syntax_t authenticate_syntax = {
235  .max_args = 0,
236  .accept_keywords=true,
237  .kvline_flags=KV_OMIT_KEYS|KV_QUOTED_QSTRING,
238  .store_raw_body=true
239 };
240 
241 /** Called when we get an AUTHENTICATE message. Check whether the
242  * authentication is valid, and if so, update the connection's state to
243  * OPEN. Reply with DONE or ERROR.
244  */
245 int
247  const control_cmd_args_t *args)
248 {
249  bool used_quoted_string = false;
250  const or_options_t *options = get_options();
251  const char *errstr = "Unknown error";
252  char *password;
253  size_t password_len;
254  int bad_cookie=0, bad_password=0;
255  smartlist_t *sl = NULL;
256 
257  if (args->kwargs == NULL) {
258  password = tor_strdup("");
259  password_len = 0;
260  } else if (args->kwargs->next) {
261  control_write_endreply(conn, 512, "Too many arguments to AUTHENTICATE.");
262  connection_mark_for_close(TO_CONN(conn));
263  return 0;
264  } else if (strcmp(args->kwargs->key, "")) {
265  control_write_endreply(conn, 512,
266  "AUTHENTICATE does not accept keyword arguments.");
267  connection_mark_for_close(TO_CONN(conn));
268  return 0;
269  } else if (strchr(args->raw_body, '\"')) {
270  used_quoted_string = true;
271  password = tor_strdup(args->kwargs->value);
272  password_len = strlen(password);
273  } else {
274  const char *hex_passwd = args->kwargs->value;
275  password_len = strlen(hex_passwd) / 2;
276  password = tor_malloc(password_len+1);
277  if (base16_decode(password, password_len+1, hex_passwd, strlen(hex_passwd))
278  != (int) password_len) {
279  control_write_endreply(conn, 551,
280  "Invalid hexadecimal encoding. Maybe you tried a plain text "
281  "password? If so, the standard requires that you put it in "
282  "double quotes.");
283  connection_mark_for_close(TO_CONN(conn));
284  tor_free(password);
285  return 0;
286  }
287  }
288 
289  if (conn->safecookie_client_hash != NULL) {
290  /* The controller has chosen safe cookie authentication; the only
291  * acceptable authentication value is the controller-to-server
292  * response. */
293 
295 
296  if (password_len != DIGEST256_LEN) {
297  log_warn(LD_CONTROL,
298  "Got safe cookie authentication response with wrong length "
299  "(%d)", (int)password_len);
300  errstr = "Wrong length for safe cookie response.";
301  goto err;
302  }
303 
304  if (tor_memneq(conn->safecookie_client_hash, password, DIGEST256_LEN)) {
305  log_warn(LD_CONTROL,
306  "Got incorrect safe cookie authentication response");
307  errstr = "Safe cookie response did not match expected value.";
308  goto err;
309  }
310 
312  goto ok;
313  }
314 
315  if (!options->CookieAuthentication && !options->HashedControlPassword &&
316  !options->HashedControlSessionPassword) {
317  /* if Tor doesn't demand any stronger authentication, then
318  * the controller can get in with anything. */
319  goto ok;
320  }
321 
322  if (options->CookieAuthentication) {
323  int also_password = options->HashedControlPassword != NULL ||
324  options->HashedControlSessionPassword != NULL;
325  if (password_len != AUTHENTICATION_COOKIE_LEN) {
326  if (!also_password) {
327  log_warn(LD_CONTROL, "Got authentication cookie with wrong length "
328  "(%d)", (int)password_len);
329  errstr = "Wrong length on authentication cookie.";
330  goto err;
331  }
332  bad_cookie = 1;
333  } else if (tor_memneq(authentication_cookie, password, password_len)) {
334  if (!also_password) {
335  log_warn(LD_CONTROL, "Got mismatched authentication cookie");
336  errstr = "Authentication cookie did not match expected value.";
337  goto err;
338  }
339  bad_cookie = 1;
340  } else {
341  goto ok;
342  }
343  }
344 
345  if (options->HashedControlPassword ||
346  options->HashedControlSessionPassword) {
347  int bad = 0;
348  smartlist_t *sl_tmp;
349  char received[DIGEST_LEN];
350  int also_cookie = options->CookieAuthentication;
351  sl = smartlist_new();
352  if (options->HashedControlPassword) {
354  if (!sl_tmp)
355  bad = 1;
356  else {
357  smartlist_add_all(sl, sl_tmp);
358  smartlist_free(sl_tmp);
359  }
360  }
361  if (options->HashedControlSessionPassword) {
363  if (!sl_tmp)
364  bad = 1;
365  else {
366  smartlist_add_all(sl, sl_tmp);
367  smartlist_free(sl_tmp);
368  }
369  }
370  if (bad) {
371  if (!also_cookie) {
372  log_warn(LD_BUG,
373  "Couldn't decode HashedControlPassword: invalid base16");
374  errstr="Couldn't decode HashedControlPassword value in configuration.";
375  goto err;
376  }
377  bad_password = 1;
378  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
379  smartlist_free(sl);
380  sl = NULL;
381  } else {
382  SMARTLIST_FOREACH(sl, char *, expected,
383  {
385  password,password_len,expected);
386  if (tor_memeq(expected + S2K_RFC2440_SPECIFIER_LEN,
387  received, DIGEST_LEN))
388  goto ok;
389  });
390  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
391  smartlist_free(sl);
392  sl = NULL;
393 
394  if (used_quoted_string)
395  errstr = "Password did not match HashedControlPassword value from "
396  "configuration";
397  else
398  errstr = "Password did not match HashedControlPassword value from "
399  "configuration. Maybe you tried a plain text password? "
400  "If so, the standard requires that you put it in double quotes.";
401  bad_password = 1;
402  if (!also_cookie)
403  goto err;
404  }
405  }
406 
407  /** We only get here if both kinds of authentication failed. */
408  tor_assert(bad_password && bad_cookie);
409  log_warn(LD_CONTROL, "Bad password or authentication cookie on controller.");
410  errstr = "Password did not match HashedControlPassword *or* authentication "
411  "cookie.";
412 
413  err:
414  tor_free(password);
415  control_printf_endreply(conn, 515, "Authentication failed: %s", errstr);
416  connection_mark_for_close(TO_CONN(conn));
417  if (sl) { /* clean up */
418  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
419  smartlist_free(sl);
420  }
421  return 0;
422  ok:
423  log_info(LD_CONTROL, "Authenticated control connection ("TOR_SOCKET_T_FORMAT
424  ")", conn->base_.s);
425  send_control_done(conn);
426  conn->base_.state = CONTROL_CONN_STATE_OPEN;
427  tor_free(password);
428  if (sl) { /* clean up */
429  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
430  smartlist_free(sl);
431  }
432  return 0;
433 }
434 
435 void
436 control_auth_free_all(void)
437 {
438  if (authentication_cookie) /* Free the auth cookie */
441 }
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:506
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:478
const or_options_t * get_options(void)
Definition: config.c:919
int init_cookie_authentication(const char *fname, const char *header, int cookie_len, int group_readable, uint8_t **cookie_out, int *cookie_is_set_out)
Definition: config.c:7443
Header file for config.c.
Header for confline.c.
Header file for connection.c.
Header file for control.c.
#define CONTROL_CONN_STATE_OPEN
Definition: control.h:20
static uint8_t * authentication_cookie
Definition: control_auth.c:37
int handle_control_authchallenge(control_connection_t *conn, const control_cmd_args_t *args)
Definition: control_auth.c:133
char * get_controller_cookie_file_name(void)
Definition: control_auth.c:48
#define AUTHENTICATION_COOKIE_LEN
Definition: control_auth.c:29
smartlist_t * decode_hashed_passwords(config_line_t *passwords)
Definition: control_auth.c:88
int handle_control_authenticate(control_connection_t *conn, const control_cmd_args_t *args)
Definition: control_auth.c:246
static int authentication_cookie_is_set
Definition: control_auth.c:33
Header file for control_auth.c.
Header file for control_cmd.c.
Definition for control_cmd_args_t.
Controller connection structure.
void control_write_endreply(control_connection_t *conn, int code, const char *s)
void send_control_done(control_connection_t *conn)
void control_printf_endreply(control_connection_t *conn, int code, const char *fmt,...)
Header file for control_proto.c.
#define HEX_DIGEST256_LEN
Definition: crypto_digest.h:37
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:477
Common functions for using (pseudo-)random number generators.
void secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret, size_t secret_len, const char *s2k_specifier)
Definition: crypto_s2k.c:203
Header for crypto_s2k.c.
#define S2K_RFC2440_SPECIFIER_LEN
Definition: crypto_s2k.h:21
Common functions for cryptographic routines.
int tor_memeq(const void *a, const void *b, size_t sz)
Definition: di_ops.c:107
#define tor_memneq(a, b, sz)
Definition: di_ops.h:21
#define DIGEST_LEN
Definition: digest_sizes.h:20
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Header for kvline.c.
#define LD_BUG
Definition: log.h:86
#define LD_CONTROL
Definition: log.h:80
#define tor_free(p)
Definition: malloc.h:52
Master header file for Tor-specific functionality.
#define TO_CONN(c)
Definition: or.h:616
Header for qstring.c.
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
uint8_t state
Definition: connection_st.h:49
tor_socket_t s
Definition: connection_st.h:96
struct smartlist_t * args
struct config_line_t * kwargs
unsigned int min_args
Definition: control_cmd.h:41
unsigned int max_args
Definition: control_cmd.h:46
char * CookieAuthFile
struct config_line_t * HashedControlPassword
int CookieAuthentication
struct config_line_t * HashedControlSessionPassword
#define tor_assert(expr)
Definition: util_bug.h:102
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:215