Mercurial > dropbear
comparison svr-authpubkey.c @ 51:095d689fed16
- Hostkey checking is mostly there, just aren't appending yet.
- Rearranged various bits of the fingerprint/base64 type code, so it
can be shared between versions
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 08 Aug 2004 16:17:05 +0000 |
parents | 45edf30ea0a6 |
children | eee77ac31ccc |
comparison
equal
deleted
inserted
replaced
49:cc59bfcdee17 | 51:095d689fed16 |
---|---|
36 #include "algo.h" | 36 #include "algo.h" |
37 | 37 |
38 #ifdef DROPBEAR_PUBKEY_AUTH | 38 #ifdef DROPBEAR_PUBKEY_AUTH |
39 | 39 |
40 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ | 40 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ |
41 #define MAX_AUTHKEYS_LINE 1000 /* max length of a line in authkeys */ | 41 #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ |
42 | 42 |
43 static int checkpubkey(unsigned char* algo, unsigned int algolen, | 43 static int checkpubkey(unsigned char* algo, unsigned int algolen, |
44 unsigned char* keyblob, unsigned int keybloblen); | 44 unsigned char* keyblob, unsigned int keybloblen); |
45 static int checkpubkeyperms(); | 45 static int checkpubkeyperms(); |
46 static void send_msg_userauth_pk_ok(unsigned char* algo, unsigned int algolen, | 46 static void send_msg_userauth_pk_ok(unsigned char* algo, unsigned int algolen, |
47 unsigned char* keyblob, unsigned int keybloblen); | 47 unsigned char* keyblob, unsigned int keybloblen); |
48 static int checkfileperm(char * filename); | 48 static int checkfileperm(char * filename); |
49 static int getauthline(buffer * line, FILE * authfile); | |
50 | 49 |
51 /* process a pubkey auth request, sending success or failure message as | 50 /* process a pubkey auth request, sending success or failure message as |
52 * appropriate */ | 51 * appropriate */ |
53 void svr_auth_pubkey() { | 52 void svr_auth_pubkey() { |
54 | 53 |
100 buf_putstring(signbuf, ses.session_id, SHA1_HASH_SIZE); | 99 buf_putstring(signbuf, ses.session_id, SHA1_HASH_SIZE); |
101 buf_putbytes(signbuf, ses.payload->data, ses.payload->pos); | 100 buf_putbytes(signbuf, ses.payload->data, ses.payload->pos); |
102 buf_setpos(signbuf, 0); | 101 buf_setpos(signbuf, 0); |
103 | 102 |
104 /* ... and finally verify the signature */ | 103 /* ... and finally verify the signature */ |
105 fp = sign_key_fingerprint(key, type); | 104 fp = sign_key_fingerprint(keyblob, keybloblen); |
106 if (buf_verify(ses.payload, key, buf_getptr(signbuf, signbuf->len), | 105 if (buf_verify(ses.payload, key, buf_getptr(signbuf, signbuf->len), |
107 signbuf->len) == DROPBEAR_SUCCESS) { | 106 signbuf->len) == DROPBEAR_SUCCESS) { |
108 dropbear_log(LOG_NOTICE, | 107 dropbear_log(LOG_NOTICE, |
109 "pubkey auth succeeded for '%s' with key %s", | 108 "pubkey auth succeeded for '%s' with key %s", |
110 ses.authstate.printableuser, fp); | 109 ses.authstate.printableuser, fp); |
158 | 157 |
159 FILE * authfile = NULL; | 158 FILE * authfile = NULL; |
160 char * filename = NULL; | 159 char * filename = NULL; |
161 int ret = DROPBEAR_FAILURE; | 160 int ret = DROPBEAR_FAILURE; |
162 buffer * line = NULL; | 161 buffer * line = NULL; |
163 buffer * decodekey = NULL; | |
164 unsigned long decodekeylen; | |
165 unsigned char* filealgo = NULL; | |
166 unsigned int filealgolen; | |
167 unsigned int len, pos; | 162 unsigned int len, pos; |
168 | 163 |
169 TRACE(("enter checkpubkey")); | 164 TRACE(("enter checkpubkey")); |
170 | 165 |
171 /* check that we can use the algo */ | 166 /* check that we can use the algo */ |
200 | 195 |
201 line = buf_new(MAX_AUTHKEYS_LINE); | 196 line = buf_new(MAX_AUTHKEYS_LINE); |
202 | 197 |
203 /* iterate through the lines */ | 198 /* iterate through the lines */ |
204 do { | 199 do { |
205 /* free reused vars */ | 200 |
206 if (decodekey) { | 201 if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { |
207 buf_free(decodekey); | |
208 decodekey = NULL; | |
209 } | |
210 m_free(filealgo); | |
211 | |
212 if (getauthline(line, authfile) == DROPBEAR_FAILURE) { | |
213 /* EOF reached */ | 202 /* EOF reached */ |
214 TRACE(("checkpubkey: authorized_keys EOF reached")); | 203 TRACE(("checkpubkey: authorized_keys EOF reached")); |
215 break; | 204 break; |
216 } | 205 } |
217 | 206 |
241 buf_setpos(line, pos); | 230 buf_setpos(line, pos); |
242 buf_setlen(line, line->pos + len); | 231 buf_setlen(line, line->pos + len); |
243 | 232 |
244 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)); | 233 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)); |
245 | 234 |
246 /* now we have the actual data */ | 235 ret = cmp_base64_key(keyblob, keybloblen, algo, algolen, line); |
247 decodekeylen = (line->len - line->pos) * 2; | 236 if (ret == DROPBEAR_SUCCESS) { |
248 decodekey = buf_new(decodekeylen); | 237 break; |
249 if (base64_decode(buf_getptr(line, line->len - line->pos), | 238 } |
250 line->len - line->pos, | 239 |
251 buf_getwriteptr(decodekey, decodekey->size), | 240 /* We continue to the next line otherwise */ |
252 &decodekeylen) != CRYPT_OK) { | |
253 TRACE(("checkpubkey: base64 decode failed")); | |
254 continue; | |
255 } | |
256 TRACE(("checkpubkey: base64_decode success")); | |
257 buf_incrlen(decodekey, decodekeylen); | |
258 | |
259 /* compare the keys */ | |
260 if (decodekeylen != keybloblen || memcmp( | |
261 buf_getptr(decodekey, decodekey->len), | |
262 keyblob, decodekey->len) != 0) { | |
263 TRACE(("checkpubkey: compare failed")); | |
264 continue; | |
265 } | |
266 | |
267 /* and also check that the algo specified and the algo in the key | |
268 * itself match */ | |
269 filealgo = buf_getstring(decodekey, &filealgolen); | |
270 if (filealgolen != algolen || memcmp(filealgo, algo, algolen) != 0) { | |
271 TRACE(("checkpubkey: algo match failed")); | |
272 continue; | |
273 } | |
274 | |
275 /* now we know this key is good */ | |
276 ret = DROPBEAR_SUCCESS; | |
277 break; | |
278 | 241 |
279 } while (1); | 242 } while (1); |
280 | 243 |
281 out: | 244 out: |
282 if (authfile) { | 245 if (authfile) { |
283 fclose(authfile); | 246 fclose(authfile); |
284 } | 247 } |
285 if (line) { | 248 if (line) { |
286 buf_free(line); | 249 buf_free(line); |
287 } | 250 } |
288 if (decodekey) { | |
289 buf_free(decodekey); | |
290 } | |
291 m_free(filename); | 251 m_free(filename); |
292 m_free(filealgo); | |
293 TRACE(("leave checkpubkey: ret=%d", ret)); | 252 TRACE(("leave checkpubkey: ret=%d", ret)); |
294 return ret; | 253 return ret; |
295 } | 254 } |
296 | 255 |
297 /* get a line from the file into buffer in the style expected for an | |
298 * authkeys file. | |
299 * Will return DROPBEAR_SUCCESS if data is read, or DROPBEAR_FAILURE on EOF.*/ | |
300 static int getauthline(buffer * line, FILE * authfile) { | |
301 | |
302 int c = EOF; | |
303 | |
304 TRACE(("enter getauthline")); | |
305 | |
306 buf_setpos(line, 0); | |
307 buf_setlen(line, 0); | |
308 | |
309 while (line->pos < line->size) { | |
310 c = fgetc(authfile); /*getc() is weird with some uClibc systems*/ | |
311 if (c == EOF || c == '\n' || c == '\r') { | |
312 goto out; | |
313 } | |
314 buf_putbyte(line, (unsigned char)c); | |
315 } | |
316 | |
317 TRACE(("leave getauthline: line too long")); | |
318 return DROPBEAR_FAILURE; | |
319 | |
320 out: | |
321 | |
322 buf_setpos(line, 0); | |
323 | |
324 /* if we didn't read anything before EOF or error, exit */ | |
325 if (c == EOF && line->pos == 0) { | |
326 TRACE(("leave getauthline: failure")); | |
327 return DROPBEAR_FAILURE; | |
328 } else { | |
329 TRACE(("leave getauthline: success")); | |
330 return DROPBEAR_SUCCESS; | |
331 } | |
332 | |
333 TRACE(("leave getauthline")); | |
334 } | |
335 | 256 |
336 /* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok, | 257 /* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok, |
337 * DROPBEAR_FAILURE otherwise. | 258 * DROPBEAR_FAILURE otherwise. |
338 * Checks that the user's homedir, ~/.ssh, and | 259 * Checks that the user's homedir, ~/.ssh, and |
339 * ~/.ssh/authorized_keys are all owned by either root or the user, and are | 260 * ~/.ssh/authorized_keys are all owned by either root or the user, and are |