Mercurial > dropbear
comparison svr-authpubkey.c @ 1674:ba6fc7afe1c5
use sigtype where appropriate
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 06 Apr 2020 23:18:26 +0800 |
parents | cc0fc5131c5c |
children | ae41624c2198 |
comparison
equal
deleted
inserted
replaced
1668:49cb3cf4bd6f | 1674:ba6fc7afe1c5 |
---|---|
68 #if DROPBEAR_SVR_PUBKEY_AUTH | 68 #if DROPBEAR_SVR_PUBKEY_AUTH |
69 | 69 |
70 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ | 70 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ |
71 #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ | 71 #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ |
72 | 72 |
73 static int checkpubkey(const char* algo, unsigned int algolen, | 73 static int checkpubkey(const char* keyalgo, unsigned int keyalgolen, |
74 const unsigned char* keyblob, unsigned int keybloblen); | 74 const unsigned char* keyblob, unsigned int keybloblen); |
75 static int checkpubkeyperms(void); | 75 static int checkpubkeyperms(void); |
76 static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, | 76 static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen, |
77 const unsigned char* keyblob, unsigned int keybloblen); | 77 const unsigned char* keyblob, unsigned int keybloblen); |
78 static int checkfileperm(char * filename); | 78 static int checkfileperm(char * filename); |
79 | 79 |
80 /* process a pubkey auth request, sending success or failure message as | 80 /* process a pubkey auth request, sending success or failure message as |
81 * appropriate */ | 81 * appropriate */ |
82 void svr_auth_pubkey(int valid_user) { | 82 void svr_auth_pubkey(int valid_user) { |
83 | 83 |
84 unsigned char testkey; /* whether we're just checking if a key is usable */ | 84 unsigned char testkey; /* whether we're just checking if a key is usable */ |
85 char* algo = NULL; /* pubkey algo */ | 85 char* sigalgo = NULL; |
86 unsigned int algolen; | 86 unsigned int sigalgolen; |
87 const char* keyalgo; | |
88 unsigned int keyalgolen; | |
87 unsigned char* keyblob = NULL; | 89 unsigned char* keyblob = NULL; |
88 unsigned int keybloblen; | 90 unsigned int keybloblen; |
89 unsigned int sign_payload_length; | 91 unsigned int sign_payload_length; |
90 buffer * signbuf = NULL; | 92 buffer * signbuf = NULL; |
91 sign_key * key = NULL; | 93 sign_key * key = NULL; |
92 char* fp = NULL; | 94 char* fp = NULL; |
93 enum signkey_type type = -1; | 95 enum signkey_type sigtype, keytype; |
94 int auth_failure = 1; | 96 int auth_failure = 1; |
95 | 97 |
96 TRACE(("enter pubkeyauth")) | 98 TRACE(("enter pubkeyauth")) |
97 | 99 |
98 /* 0 indicates user just wants to check if key can be used, 1 is an | 100 /* 0 indicates user just wants to check if key can be used, 1 is an |
99 * actual attempt*/ | 101 * actual attempt*/ |
100 testkey = (buf_getbool(ses.payload) == 0); | 102 testkey = (buf_getbool(ses.payload) == 0); |
101 | 103 |
102 algo = buf_getstring(ses.payload, &algolen); | 104 sigalgo = buf_getstring(ses.payload, &sigalgolen); |
105 sigtype = signature_type_from_name(sigalgo, sigalgolen); | |
106 keytype = signkey_type_from_signature(sigtype); | |
107 keyalgo = signkey_name_from_type(keytype, &keyalgolen); | |
108 | |
103 keybloblen = buf_getint(ses.payload); | 109 keybloblen = buf_getint(ses.payload); |
104 keyblob = buf_getptr(ses.payload, keybloblen); | 110 keyblob = buf_getptr(ses.payload, keybloblen); |
105 | 111 |
106 if (!valid_user) { | 112 if (!valid_user) { |
107 /* Return failure once we have read the contents of the packet | 113 /* Return failure once we have read the contents of the packet |
115 if (svr_ses.plugin_instance != NULL) { | 121 if (svr_ses.plugin_instance != NULL) { |
116 char *options_buf; | 122 char *options_buf; |
117 if (svr_ses.plugin_instance->checkpubkey( | 123 if (svr_ses.plugin_instance->checkpubkey( |
118 svr_ses.plugin_instance, | 124 svr_ses.plugin_instance, |
119 &ses.plugin_session, | 125 &ses.plugin_session, |
120 algo, | 126 keyalgo, |
121 algolen, | 127 keyalgolen, |
122 keyblob, | 128 keyblob, |
123 keybloblen, | 129 keybloblen, |
124 ses.authstate.username) == DROPBEAR_SUCCESS) { | 130 ses.authstate.username) == DROPBEAR_SUCCESS) { |
125 /* Success */ | 131 /* Success */ |
126 auth_failure = 0; | 132 auth_failure = 0; |
144 } | 150 } |
145 } | 151 } |
146 #endif | 152 #endif |
147 /* check if the key is valid */ | 153 /* check if the key is valid */ |
148 if (auth_failure) { | 154 if (auth_failure) { |
149 auth_failure = checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE; | 155 auth_failure = checkpubkey(keyalgo, keyalgolen, keyblob, keybloblen) == DROPBEAR_FAILURE; |
150 } | 156 } |
151 | 157 |
152 if (auth_failure) { | 158 if (auth_failure) { |
153 send_msg_userauth_failure(0, 0); | 159 send_msg_userauth_failure(0, 0); |
154 goto out; | 160 goto out; |
155 } | 161 } |
156 | 162 |
157 /* let them know that the key is ok to use */ | 163 /* let them know that the key is ok to use */ |
158 if (testkey) { | 164 if (testkey) { |
159 send_msg_userauth_pk_ok(algo, algolen, keyblob, keybloblen); | 165 send_msg_userauth_pk_ok(sigalgo, sigalgolen, keyblob, keybloblen); |
160 goto out; | 166 goto out; |
161 } | 167 } |
162 | 168 |
163 /* now we can actually verify the signature */ | 169 /* now we can actually verify the signature */ |
164 | 170 |
165 /* get the key */ | 171 /* get the key */ |
166 key = new_sign_key(); | 172 key = new_sign_key(); |
167 type = DROPBEAR_SIGNKEY_ANY; | 173 if (buf_get_pub_key(ses.payload, key, &keytype) == DROPBEAR_FAILURE) { |
168 if (buf_get_pub_key(ses.payload, key, &type) == DROPBEAR_FAILURE) { | |
169 send_msg_userauth_failure(0, 1); | 174 send_msg_userauth_failure(0, 1); |
170 goto out; | 175 goto out; |
171 } | 176 } |
172 | 177 |
173 /* create the data which has been signed - this a string containing | 178 /* create the data which has been signed - this a string containing |
186 | 191 |
187 buf_setpos(signbuf, 0); | 192 buf_setpos(signbuf, 0); |
188 | 193 |
189 /* ... and finally verify the signature */ | 194 /* ... and finally verify the signature */ |
190 fp = sign_key_fingerprint(keyblob, keybloblen); | 195 fp = sign_key_fingerprint(keyblob, keybloblen); |
191 if (buf_verify(ses.payload, key, signbuf) == DROPBEAR_SUCCESS) { | 196 if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) { |
192 dropbear_log(LOG_NOTICE, | 197 dropbear_log(LOG_NOTICE, |
193 "Pubkey auth succeeded for '%s' with key %s from %s", | 198 "Pubkey auth succeeded for '%s' with key %s from %s", |
194 ses.authstate.pw_name, fp, svr_ses.addrstring); | 199 ses.authstate.pw_name, fp, svr_ses.addrstring); |
195 send_msg_userauth_success(); | 200 send_msg_userauth_success(); |
196 #if DROPBEAR_PLUGIN | 201 #if DROPBEAR_PLUGIN |
211 out: | 216 out: |
212 /* cleanup stuff */ | 217 /* cleanup stuff */ |
213 if (signbuf) { | 218 if (signbuf) { |
214 buf_free(signbuf); | 219 buf_free(signbuf); |
215 } | 220 } |
216 if (algo) { | 221 if (sigalgo) { |
217 m_free(algo); | 222 m_free(sigalgo); |
218 } | 223 } |
219 if (key) { | 224 if (key) { |
220 sign_key_free(key); | 225 sign_key_free(key); |
221 key = NULL; | 226 key = NULL; |
222 } | 227 } |
228 } | 233 } |
229 | 234 |
230 /* Reply that the key is valid for auth, this is sent when the user sends | 235 /* Reply that the key is valid for auth, this is sent when the user sends |
231 * a straight copy of their pubkey to test, to avoid having to perform | 236 * a straight copy of their pubkey to test, to avoid having to perform |
232 * expensive signing operations with a worthless key */ | 237 * expensive signing operations with a worthless key */ |
233 static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, | 238 static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen, |
234 const unsigned char* keyblob, unsigned int keybloblen) { | 239 const unsigned char* keyblob, unsigned int keybloblen) { |
235 | 240 |
236 TRACE(("enter send_msg_userauth_pk_ok")) | 241 TRACE(("enter send_msg_userauth_pk_ok")) |
237 CHECKCLEARTOWRITE(); | 242 CHECKCLEARTOWRITE(); |
238 | 243 |
239 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK); | 244 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK); |
240 buf_putstring(ses.writepayload, algo, algolen); | 245 buf_putstring(ses.writepayload, sigalgo, sigalgolen); |
241 buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen); | 246 buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen); |
242 | 247 |
243 encrypt_packet(); | 248 encrypt_packet(); |
244 TRACE(("leave send_msg_userauth_pk_ok")) | 249 TRACE(("leave send_msg_userauth_pk_ok")) |
245 | 250 |
352 | 357 |
353 | 358 |
354 /* Checks whether a specified publickey (and associated algorithm) is an | 359 /* Checks whether a specified publickey (and associated algorithm) is an |
355 * acceptable key for authentication */ | 360 * acceptable key for authentication */ |
356 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ | 361 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ |
357 static int checkpubkey(const char* algo, unsigned int algolen, | 362 static int checkpubkey(const char* keyalgo, unsigned int keyalgolen, |
358 const unsigned char* keyblob, unsigned int keybloblen) { | 363 const unsigned char* keyblob, unsigned int keybloblen) { |
359 | 364 |
360 FILE * authfile = NULL; | 365 FILE * authfile = NULL; |
361 char * filename = NULL; | 366 char * filename = NULL; |
362 int ret = DROPBEAR_FAILURE; | 367 int ret = DROPBEAR_FAILURE; |
366 uid_t origuid; | 371 uid_t origuid; |
367 gid_t origgid; | 372 gid_t origgid; |
368 | 373 |
369 TRACE(("enter checkpubkey")) | 374 TRACE(("enter checkpubkey")) |
370 | 375 |
371 /* check that we can use the algo */ | |
372 if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) { | |
373 dropbear_log(LOG_WARNING, | |
374 "Pubkey auth attempt with unknown algo for '%s' from %s", | |
375 ses.authstate.pw_name, svr_ses.addrstring); | |
376 goto out; | |
377 } | |
378 | |
379 /* check file permissions, also whether file exists */ | 376 /* check file permissions, also whether file exists */ |
380 if (checkpubkeyperms() == DROPBEAR_FAILURE) { | 377 if (checkpubkeyperms() == DROPBEAR_FAILURE) { |
381 TRACE(("bad authorized_keys permissions, or file doesn't exist")) | 378 TRACE(("bad authorized_keys permissions, or file doesn't exist")) |
382 goto out; | 379 goto out; |
383 } | 380 } |
425 TRACE(("checkpubkey: authorized_keys EOF reached")) | 422 TRACE(("checkpubkey: authorized_keys EOF reached")) |
426 break; | 423 break; |
427 } | 424 } |
428 line_num++; | 425 line_num++; |
429 | 426 |
430 ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen); | 427 ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, keyblob, keybloblen); |
431 if (ret == DROPBEAR_SUCCESS) { | 428 if (ret == DROPBEAR_SUCCESS) { |
432 break; | 429 break; |
433 } | 430 } |
434 | 431 |
435 /* We continue to the next line otherwise */ | 432 /* We continue to the next line otherwise */ |