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"
12 #include "core/mainloop/connection.h"
13 #include "feature/control/control.h"
14 #include "feature/control/control_cmd.h"
15 #include "feature/control/control_auth.h"
16 #include "feature/control/control_cmd_args_st.h"
17 #include "feature/control/control_connection_st.h"
18 #include "feature/control/control_proto.h"
19 #include "lib/crypt_ops/crypto_rand.h"
20 #include "lib/crypt_ops/crypto_util.h"
21 #include "lib/encoding/confline.h"
22 #include "lib/encoding/kvline.h"
23 #include "lib/encoding/qstring.h"
24 
25 #include "lib/crypt_ops/crypto_s2k.h"
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. */
33 static int authentication_cookie_is_set = 0;
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 *
get_controller_cookie_file_name(void)48 get_controller_cookie_file_name(void)
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
init_control_cookie_authentication(int enabled)62 init_control_cookie_authentication(int enabled)
63 {
64   char *fname = NULL;
65   int retval;
66 
67   if (!enabled) {
68     authentication_cookie_is_set = 0;
69     return 0;
70   }
71 
72   fname = get_controller_cookie_file_name();
73   retval = init_cookie_authentication(fname, "", /* no header */
74                                       AUTHENTICATION_COOKIE_LEN,
75                                    get_options()->CookieAuthFileGroupReadable,
76                                       &authentication_cookie,
77                                       &authentication_cookie_is_set);
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  */
87 smartlist_t *
decode_hashed_passwords(config_line_t * passwords)88 decode_hashed_passwords(config_line_t *passwords)
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))
101                         != S2K_RFC2440_SPECIFIER_LEN + DIGEST_LEN
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))
107             != S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) {
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
handle_control_authchallenge(control_connection_t * conn,const control_cmd_args_t * args)133 handle_control_authchallenge(control_connection_t *conn,
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   }
149   if (!authentication_cookie_is_set) {
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. */
187   tor_assert(authentication_cookie != NULL);
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);
195     memcpy(tmp, authentication_cookie, AUTHENTICATION_COOKIE_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
handle_control_authenticate(control_connection_t * conn,const control_cmd_args_t * args)246 handle_control_authenticate(control_connection_t *conn,
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 
294     tor_assert(authentication_cookie_is_set);
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 
311     tor_free(conn->safecookie_client_hash);
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) {
353       sl_tmp = decode_hashed_passwords(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) {
362       sl_tmp = decode_hashed_passwords(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       {
384         secret_to_key_rfc2440(received,DIGEST_LEN,
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
control_auth_free_all(void)436 control_auth_free_all(void)
437 {
438   if (authentication_cookie) /* Free the auth cookie */
439     tor_free(authentication_cookie);
440   authentication_cookie_is_set = 0;
441 }
442