1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
7 * \brief Authentication for Tor's control-socket interface.
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. */
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
);
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. */
62 init_control_cookie_authentication(int enabled
)
68 authentication_cookie_is_set
= 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
);
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
88 decode_hashed_passwords(config_line_t
*passwords
)
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) {
106 if (base64_decode(decoded
, sizeof(decoded
), hashed
, strlen(hashed
))
107 != S2K_RFC2440_SPECIFIER_LEN
+DIGEST_LEN
) {
112 tor_memdup(decoded
, S2K_RFC2440_SPECIFIER_LEN
+DIGEST_LEN
));
118 SMARTLIST_FOREACH(sl
, char*, cp
, tor_free(cp
));
123 const control_cmd_syntax_t authchallenge_syntax
= {
126 .accept_keywords
=true,
127 .kvline_flags
=KV_OMIT_KEYS
|KV_QUOTED_QSTRING
,
131 /** Called when we get an AUTHCHALLENGE command. */
133 handle_control_authchallenge(control_connection_t
*conn
,
134 const control_cmd_args_t
*args
)
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 "
149 if (!authentication_cookie_is_set
) {
150 control_write_endreply(conn
, 515, "Cookie authentication is disabled");
153 if (args
->kwargs
== NULL
|| args
->kwargs
->next
!= NULL
) {
154 control_write_endreply(conn
, 512,
155 "Wrong number of arguments for AUTHCHALLENGE");
158 if (strcmp(args
->kwargs
->key
, "")) {
159 control_write_endreply(conn
, 512,
160 "AUTHCHALLENGE does not accept keyword "
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
);
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
);
183 crypto_rand(server_nonce
, SAFECOOKIE_SERVER_NONCE_LEN
);
185 /* Now compute and send the server-to-controller response, and the
187 tor_assert(authentication_cookie
!= NULL
);
190 size_t tmp_len
= (AUTHENTICATION_COOKIE_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
),
206 crypto_hmac_sha256(client_hash
,
207 SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT
,
208 strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT
),
212 conn
->safecookie_client_hash
= client_hash
;
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",
225 server_nonce_encoded
);
227 tor_free(client_nonce
);
230 connection_mark_for_close(TO_CONN(conn
));
234 const control_cmd_syntax_t authenticate_syntax
= {
236 .accept_keywords
=true,
237 .kvline_flags
=KV_OMIT_KEYS
|KV_QUOTED_QSTRING
,
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";
254 int bad_cookie
=0, bad_password
=0;
255 smartlist_t
*sl
= NULL
;
257 if (args
->kwargs
== NULL
) {
258 password
= tor_strdup("");
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
));
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
));
269 } else if (strchr(args
->raw_body
, '\"')) {
270 used_quoted_string
= true;
271 password
= tor_strdup(args
->kwargs
->value
);
272 password_len
= strlen(password
);
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 "
283 connection_mark_for_close(TO_CONN(conn
));
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
294 tor_assert(authentication_cookie_is_set
);
296 if (password_len
!= DIGEST256_LEN
) {
298 "Got safe cookie authentication response with wrong length "
299 "(%d)", (int)password_len
);
300 errstr
= "Wrong length for safe cookie response.";
304 if (tor_memneq(conn
->safecookie_client_hash
, password
, DIGEST256_LEN
)) {
306 "Got incorrect safe cookie authentication response");
307 errstr
= "Safe cookie response did not match expected value.";
311 tor_free(conn
->safecookie_client_hash
);
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. */
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.";
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.";
345 if (options
->HashedControlPassword
||
346 options
->HashedControlSessionPassword
) {
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
);
357 smartlist_add_all(sl
, sl_tmp
);
358 smartlist_free(sl_tmp
);
361 if (options
->HashedControlSessionPassword
) {
362 sl_tmp
= decode_hashed_passwords(options
->HashedControlSessionPassword
);
366 smartlist_add_all(sl
, sl_tmp
);
367 smartlist_free(sl_tmp
);
373 "Couldn't decode HashedControlPassword: invalid base16");
374 errstr
="Couldn't decode HashedControlPassword value in configuration.";
378 SMARTLIST_FOREACH(sl
, char *, str
, tor_free(str
));
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
))
390 SMARTLIST_FOREACH(sl
, char *, str
, tor_free(str
));
394 if (used_quoted_string
)
395 errstr
= "Password did not match HashedControlPassword value from "
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.";
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 "
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
));
423 log_info(LD_CONTROL
, "Authenticated control connection ("TOR_SOCKET_T_FORMAT
425 send_control_done(conn
);
426 conn
->base_
.state
= CONTROL_CONN_STATE_OPEN
;
428 if (sl
) { /* clean up */
429 SMARTLIST_FOREACH(sl
, char *, str
, tor_free(str
));
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;