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