tor  0.4.2.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-2019, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
4 
10 #include "core/or/or.h"
11 #include "app/config/config.h"
17 #include "feature/control/control_connection_st.h"
21 #include "lib/encoding/confline.h"
22 #include "lib/encoding/kvline.h"
23 #include "lib/encoding/qstring.h"
24 
26 
29 #define AUTHENTICATION_COOKIE_LEN 32
30 
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 
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 
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 
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  /* connection_write_str_to_buf("512 AUTHCHALLENGE requires exactly "
155  "2 arguments.\r\n", conn);
156  */
157  control_printf_endreply(conn, 512,
158  "AUTHCHALLENGE dislikes argument list %s",
159  escaped(args->raw_body));
160  goto fail;
161  }
162  if (strcmp(args->kwargs->key, "")) {
163  control_write_endreply(conn, 512,
164  "AUTHCHALLENGE does not accept keyword "
165  "arguments.");
166  goto fail;
167  }
168 
169  bool contains_quote = strchr(args->raw_body, '\"');
170  if (contains_quote) {
171  /* The nonce was quoted */
172  client_nonce = tor_strdup(args->kwargs->value);
173  client_nonce_len = strlen(client_nonce);
174  } else {
175  /* The nonce was should be in hex. */
176  const char *hex_nonce = args->kwargs->value;
177  client_nonce_len = strlen(hex_nonce) / 2;
178  client_nonce = tor_malloc(client_nonce_len);
179  if (base16_decode(client_nonce, client_nonce_len, hex_nonce,
180  strlen(hex_nonce)) != (int)client_nonce_len) {
181  control_write_endreply(conn, 513, "Invalid base16 client nonce");
182  tor_free(client_nonce);
183  goto fail;
184  }
185  }
186 
187  crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
188 
189  /* Now compute and send the server-to-controller response, and the
190  * server's nonce. */
192 
193  {
194  size_t tmp_len = (AUTHENTICATION_COOKIE_LEN +
195  client_nonce_len +
196  SAFECOOKIE_SERVER_NONCE_LEN);
197  char *tmp = tor_malloc_zero(tmp_len);
198  char *client_hash = tor_malloc_zero(DIGEST256_LEN);
200  memcpy(tmp + AUTHENTICATION_COOKIE_LEN, client_nonce, client_nonce_len);
201  memcpy(tmp + AUTHENTICATION_COOKIE_LEN + client_nonce_len,
202  server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
203 
204  crypto_hmac_sha256(server_hash,
205  SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
206  strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
207  tmp,
208  tmp_len);
209 
210  crypto_hmac_sha256(client_hash,
211  SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
212  strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
213  tmp,
214  tmp_len);
215 
216  conn->safecookie_client_hash = client_hash;
217 
218  tor_free(tmp);
219  }
220 
221  base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
222  server_hash, sizeof(server_hash));
223  base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
224  server_nonce, sizeof(server_nonce));
225 
226  control_printf_endreply(conn, 250,
227  "AUTHCHALLENGE SERVERHASH=%s SERVERNONCE=%s",
228  server_hash_encoded,
229  server_nonce_encoded);
230 
231  tor_free(client_nonce);
232  return 0;
233  fail:
234  connection_mark_for_close(TO_CONN(conn));
235  return -1;
236 }
237 
238 const control_cmd_syntax_t authenticate_syntax = {
239  .max_args = 0,
240  .accept_keywords=true,
241  .kvline_flags=KV_OMIT_KEYS|KV_QUOTED_QSTRING,
242  .store_raw_body=true
243 };
244 
249 int
251  const control_cmd_args_t *args)
252 {
253  bool used_quoted_string = false;
254  const or_options_t *options = get_options();
255  const char *errstr = "Unknown error";
256  char *password;
257  size_t password_len;
258  int bad_cookie=0, bad_password=0;
259  smartlist_t *sl = NULL;
260 
261  if (args->kwargs == NULL) {
262  password = tor_strdup("");
263  password_len = 0;
264  } else if (args->kwargs->next) {
265  control_write_endreply(conn, 512, "Too many arguments to AUTHENTICATE.");
266  connection_mark_for_close(TO_CONN(conn));
267  return 0;
268  } else if (strcmp(args->kwargs->key, "")) {
269  control_write_endreply(conn, 512,
270  "AUTHENTICATE does not accept keyword arguments.");
271  connection_mark_for_close(TO_CONN(conn));
272  return 0;
273  } else if (strchr(args->raw_body, '\"')) {
274  used_quoted_string = true;
275  password = tor_strdup(args->kwargs->value);
276  password_len = strlen(password);
277  } else {
278  const char *hex_passwd = args->kwargs->value;
279  password_len = strlen(hex_passwd) / 2;
280  password = tor_malloc(password_len+1);
281  if (base16_decode(password, password_len+1, hex_passwd, strlen(hex_passwd))
282  != (int) password_len) {
283  control_write_endreply(conn, 551,
284  "Invalid hexadecimal encoding. Maybe you tried a plain text "
285  "password? If so, the standard requires that you put it in "
286  "double quotes.");
287  connection_mark_for_close(TO_CONN(conn));
288  tor_free(password);
289  return 0;
290  }
291  }
292 
293  if (conn->safecookie_client_hash != NULL) {
294  /* The controller has chosen safe cookie authentication; the only
295  * acceptable authentication value is the controller-to-server
296  * response. */
297 
299 
300  if (password_len != DIGEST256_LEN) {
301  log_warn(LD_CONTROL,
302  "Got safe cookie authentication response with wrong length "
303  "(%d)", (int)password_len);
304  errstr = "Wrong length for safe cookie response.";
305  goto err;
306  }
307 
308  if (tor_memneq(conn->safecookie_client_hash, password, DIGEST256_LEN)) {
309  log_warn(LD_CONTROL,
310  "Got incorrect safe cookie authentication response");
311  errstr = "Safe cookie response did not match expected value.";
312  goto err;
313  }
314 
316  goto ok;
317  }
318 
319  if (!options->CookieAuthentication && !options->HashedControlPassword &&
320  !options->HashedControlSessionPassword) {
321  /* if Tor doesn't demand any stronger authentication, then
322  * the controller can get in with anything. */
323  goto ok;
324  }
325 
326  if (options->CookieAuthentication) {
327  int also_password = options->HashedControlPassword != NULL ||
328  options->HashedControlSessionPassword != NULL;
329  if (password_len != AUTHENTICATION_COOKIE_LEN) {
330  if (!also_password) {
331  log_warn(LD_CONTROL, "Got authentication cookie with wrong length "
332  "(%d)", (int)password_len);
333  errstr = "Wrong length on authentication cookie.";
334  goto err;
335  }
336  bad_cookie = 1;
337  } else if (tor_memneq(authentication_cookie, password, password_len)) {
338  if (!also_password) {
339  log_warn(LD_CONTROL, "Got mismatched authentication cookie");
340  errstr = "Authentication cookie did not match expected value.";
341  goto err;
342  }
343  bad_cookie = 1;
344  } else {
345  goto ok;
346  }
347  }
348 
349  if (options->HashedControlPassword ||
350  options->HashedControlSessionPassword) {
351  int bad = 0;
352  smartlist_t *sl_tmp;
353  char received[DIGEST_LEN];
354  int also_cookie = options->CookieAuthentication;
355  sl = smartlist_new();
356  if (options->HashedControlPassword) {
358  if (!sl_tmp)
359  bad = 1;
360  else {
361  smartlist_add_all(sl, sl_tmp);
362  smartlist_free(sl_tmp);
363  }
364  }
365  if (options->HashedControlSessionPassword) {
367  if (!sl_tmp)
368  bad = 1;
369  else {
370  smartlist_add_all(sl, sl_tmp);
371  smartlist_free(sl_tmp);
372  }
373  }
374  if (bad) {
375  if (!also_cookie) {
376  log_warn(LD_BUG,
377  "Couldn't decode HashedControlPassword: invalid base16");
378  errstr="Couldn't decode HashedControlPassword value in configuration.";
379  goto err;
380  }
381  bad_password = 1;
382  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
383  smartlist_free(sl);
384  sl = NULL;
385  } else {
386  SMARTLIST_FOREACH(sl, char *, expected,
387  {
389  password,password_len,expected);
390  if (tor_memeq(expected + S2K_RFC2440_SPECIFIER_LEN,
391  received, DIGEST_LEN))
392  goto ok;
393  });
394  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
395  smartlist_free(sl);
396  sl = NULL;
397 
398  if (used_quoted_string)
399  errstr = "Password did not match HashedControlPassword value from "
400  "configuration";
401  else
402  errstr = "Password did not match HashedControlPassword value from "
403  "configuration. Maybe you tried a plain text password? "
404  "If so, the standard requires that you put it in double quotes.";
405  bad_password = 1;
406  if (!also_cookie)
407  goto err;
408  }
409  }
410 
412  tor_assert(bad_password && bad_cookie);
413  log_warn(LD_CONTROL, "Bad password or authentication cookie on controller.");
414  errstr = "Password did not match HashedControlPassword *or* authentication "
415  "cookie.";
416 
417  err:
418  tor_free(password);
419  control_printf_endreply(conn, 515, "Authentication failed: %s", errstr);
420  connection_mark_for_close(TO_CONN(conn));
421  if (sl) { /* clean up */
422  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
423  smartlist_free(sl);
424  }
425  return 0;
426  ok:
427  log_info(LD_CONTROL, "Authenticated control connection ("TOR_SOCKET_T_FORMAT
428  ")", conn->base_.s);
429  send_control_done(conn);
430  conn->base_.state = CONTROL_CONN_STATE_OPEN;
431  tor_free(password);
432  if (sl) { /* clean up */
433  SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
434  smartlist_free(sl);
435  }
436  return 0;
437 }
438 
439 void
440 control_auth_free_all(void)
441 {
442  if (authentication_cookie) /* Free the auth cookie */
445 }
tor_socket_t s
Definition: connection_st.h:88
Header for confline.c.
Common functions for using (pseudo-)random number generators.
Header file for control_auth.c.
#define TO_CONN(c)
Definition: or.h:735
char * CookieAuthFile
Header file for connection.c.
struct smartlist_t * args
uint8_t state
Definition: connection_st.h:44
void smartlist_add(smartlist_t *sl, void *element)
#define CONTROL_CONN_STATE_OPEN
Definition: control.h:19
Header file for config.c.
#define HEX_DIGEST256_LEN
Definition: crypto_digest.h:37
void send_control_done(control_connection_t *conn)
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:206
#define tor_free(p)
Definition: malloc.h:52
char * get_controller_cookie_file_name(void)
Definition: control_auth.c:48
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Definition for control_cmd_args_t.
unsigned int max_args
Definition: control_cmd.h:46
void control_printf_endreply(control_connection_t *conn, int code, const char *fmt,...)
Common functions for cryptographic routines.
tor_assert(buffer)
#define LD_CONTROL
Definition: log.h:77
int handle_control_authchallenge(control_connection_t *conn, const control_cmd_args_t *args)
Definition: control_auth.c:133
int tor_memeq(const void *a, const void *b, size_t sz)
Definition: di_ops.c:107
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
struct config_line_t * HashedControlSessionPassword
#define DIGEST_LEN
Definition: digest_sizes.h:20
Master header file for Tor-specific functionality.
Header for crypto_s2k.c.
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:478
Header file for control_cmd.c.
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:8445
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:250
#define AUTHENTICATION_COOKIE_LEN
Definition: control_auth.c:29
struct config_line_t * HashedControlPassword
static int authentication_cookie_is_set
Definition: control_auth.c:33
static uint8_t * authentication_cookie
Definition: control_auth.c:37
#define S2K_RFC2440_SPECIFIER_LEN
Definition: crypto_s2k.h:21
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:396
#define SMARTLIST_FOREACH(sl, type, var, cmd)
const char * escaped(const char *s)
Definition: escape.c:126
Header for qstring.c.
void control_write_endreply(control_connection_t *conn, int code, const char *s)
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
Header for kvline.c.
Header file for control.c.
Header file for control_proto.c.
unsigned int min_args
Definition: control_cmd.h:41
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition: binascii.c:506
int CookieAuthentication
struct config_line_t * kwargs
#define LD_BUG
Definition: log.h:83