Control port STREAM XON/XOFF status event notification
[tor.git] / src / feature / control / control_auth.c
blob2af6517493e1b8f363bfde65d197bf6f25813631
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
5 /**
6 * \file control_auth.c
7 * \brief Authentication for Tor's control-socket interface.
8 **/
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"
25 #include "lib/crypt_ops/crypto_s2k.h"
27 /** If we're using cookie-type authentication, how long should our cookies be?
29 #define AUTHENTICATION_COOKIE_LEN 32
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;
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
45 /** Helper: Return a newly allocated string containing a path to the
46 * file where we store our authentication cookie. */
47 char *
48 get_controller_cookie_file_name(void)
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");
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)
64 char *fname = NULL;
65 int retval;
67 if (!enabled) {
68 authentication_cookie_is_set = 0;
69 return 0;
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;
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.
87 smartlist_t *
88 decode_hashed_passwords(config_line_t *passwords)
90 char decoded[64];
91 config_line_t *cl;
92 smartlist_t *sl = smartlist_new();
94 tor_assert(passwords);
96 for (cl = passwords; cl; cl = cl->next) {
97 const char *hashed = cl->value;
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;
105 } else {
106 if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
107 != S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) {
108 goto err;
111 smartlist_add(sl,
112 tor_memdup(decoded, S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN));
115 return sl;
117 err:
118 SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
119 smartlist_free(sl);
120 return NULL;
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
131 /** Called when we get an AUTHCHALLENGE command. */
133 handle_control_authchallenge(control_connection_t *conn,
134 const control_cmd_args_t *args)
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];
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;
149 if (!authentication_cookie_is_set) {
150 control_write_endreply(conn, 515, "Cookie authentication is disabled");
151 goto fail;
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;
158 if (strcmp(args->kwargs->key, "")) {
159 control_write_endreply(conn, 512,
160 "AUTHCHALLENGE does not accept keyword "
161 "arguments.");
162 goto fail;
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;
183 crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
185 /* Now compute and send the server-to-controller response, and the
186 * server's nonce. */
187 tor_assert(authentication_cookie != NULL);
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);
200 crypto_hmac_sha256(server_hash,
201 SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
202 strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
203 tmp,
204 tmp_len);
206 crypto_hmac_sha256(client_hash,
207 SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
208 strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
209 tmp,
210 tmp_len);
212 conn->safecookie_client_hash = client_hash;
214 tor_free(tmp);
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));
222 control_printf_endreply(conn, 250,
223 "AUTHCHALLENGE SERVERHASH=%s SERVERNONCE=%s",
224 server_hash_encoded,
225 server_nonce_encoded);
227 tor_free(client_nonce);
228 return 0;
229 fail:
230 connection_mark_for_close(TO_CONN(conn));
231 return -1;
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
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.
246 handle_control_authenticate(control_connection_t *conn,
247 const control_cmd_args_t *args)
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;
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;
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. */
294 tor_assert(authentication_cookie_is_set);
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;
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;
311 tor_free(conn->safecookie_client_hash);
312 goto ok;
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;
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;
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;
339 bad_cookie = 1;
340 } else {
341 goto ok;
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);
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);
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;
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,
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;
390 SMARTLIST_FOREACH(sl, char *, str, tor_free(str));
391 smartlist_free(sl);
392 sl = NULL;
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;
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.";
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);
421 return 0;
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);
432 return 0;
435 void
436 control_auth_free_all(void)
438 if (authentication_cookie) /* Free the auth cookie */
439 tor_free(authentication_cookie);
440 authentication_cookie_is_set = 0;