Mercurial > dropbear
comparison svr-authpubkey.c @ 1368:10df23099071 fuzz
split out checkpubkey_line() separately
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Tue, 23 May 2017 22:29:21 +0800 |
parents | 8747c2b19152 |
children | de1d895b1cae |
comparison
equal
deleted
inserted
replaced
1367:00fb0a1f9b70 | 1368:10df23099071 |
---|---|
186 encrypt_packet(); | 186 encrypt_packet(); |
187 TRACE(("leave send_msg_userauth_pk_ok")) | 187 TRACE(("leave send_msg_userauth_pk_ok")) |
188 | 188 |
189 } | 189 } |
190 | 190 |
191 static int checkpubkey_line(buffer* line, int line_num, char* filename, | |
192 const char* algo, unsigned int algolen, | |
193 const unsigned char* keyblob, unsigned int keybloblen) { | |
194 buffer *options_buf = NULL; | |
195 unsigned int pos, len; | |
196 int ret = DROPBEAR_FAILURE; | |
197 | |
198 if (line->len < MIN_AUTHKEYS_LINE) { | |
199 TRACE(("checkpubkey: line too short")) | |
200 return DROPBEAR_FAILURE; /* line is too short for it to be a valid key */ | |
201 } | |
202 | |
203 /* check the key type */ | |
204 if (strncmp((const char *) buf_getptr(line, algolen), algo, algolen) != 0) { | |
205 int is_comment = 0; | |
206 unsigned char *options_start = NULL; | |
207 int options_len = 0; | |
208 int escape, quoted; | |
209 | |
210 /* skip over any comments or leading whitespace */ | |
211 while (line->pos < line->len) { | |
212 const char c = buf_getbyte(line); | |
213 if (c == ' ' || c == '\t') { | |
214 continue; | |
215 } else if (c == '#') { | |
216 is_comment = 1; | |
217 break; | |
218 } | |
219 buf_incrpos(line, -1); | |
220 break; | |
221 } | |
222 if (is_comment) { | |
223 /* next line */ | |
224 goto out; | |
225 } | |
226 | |
227 /* remember start of options */ | |
228 options_start = buf_getptr(line, 1); | |
229 quoted = 0; | |
230 escape = 0; | |
231 options_len = 0; | |
232 | |
233 /* figure out where the options are */ | |
234 while (line->pos < line->len) { | |
235 const char c = buf_getbyte(line); | |
236 if (!quoted && (c == ' ' || c == '\t')) { | |
237 break; | |
238 } | |
239 escape = (!escape && c == '\\'); | |
240 if (!escape && c == '"') { | |
241 quoted = !quoted; | |
242 } | |
243 options_len++; | |
244 } | |
245 options_buf = buf_new(options_len); | |
246 buf_putbytes(options_buf, options_start, options_len); | |
247 | |
248 /* compare the algorithm. +3 so we have enough bytes to read a space and some base64 characters too. */ | |
249 if (line->pos + algolen+3 > line->len) { | |
250 goto out; | |
251 } | |
252 if (strncmp((const char *) buf_getptr(line, algolen), algo, algolen) != 0) { | |
253 goto out; | |
254 } | |
255 } | |
256 buf_incrpos(line, algolen); | |
257 | |
258 /* check for space (' ') character */ | |
259 if (buf_getbyte(line) != ' ') { | |
260 TRACE(("checkpubkey: space character expected, isn't there")) | |
261 goto out; | |
262 } | |
263 | |
264 /* truncate the line at the space after the base64 data */ | |
265 pos = line->pos; | |
266 for (len = 0; line->pos < line->len; len++) { | |
267 if (buf_getbyte(line) == ' ') break; | |
268 } | |
269 buf_setpos(line, pos); | |
270 buf_setlen(line, line->pos + len); | |
271 | |
272 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)) | |
273 | |
274 ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algo, algolen, line, NULL); | |
275 | |
276 if (ret == DROPBEAR_SUCCESS && options_buf) { | |
277 ret = svr_add_pubkey_options(options_buf, line_num, filename); | |
278 } | |
279 | |
280 out: | |
281 if (options_buf) { | |
282 buf_free(options_buf); | |
283 } | |
284 return ret; | |
285 } | |
286 | |
287 | |
191 /* Checks whether a specified publickey (and associated algorithm) is an | 288 /* Checks whether a specified publickey (and associated algorithm) is an |
192 * acceptable key for authentication */ | 289 * acceptable key for authentication */ |
193 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ | 290 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ |
194 static int checkpubkey(char* algo, unsigned int algolen, | 291 static int checkpubkey(char* algo, unsigned int algolen, |
195 unsigned char* keyblob, unsigned int keybloblen) { | 292 unsigned char* keyblob, unsigned int keybloblen) { |
196 | 293 |
197 FILE * authfile = NULL; | 294 FILE * authfile = NULL; |
198 char * filename = NULL; | 295 char * filename = NULL; |
199 int ret = DROPBEAR_FAILURE; | 296 int ret = DROPBEAR_FAILURE; |
200 buffer * line = NULL; | 297 buffer * line = NULL; |
201 unsigned int len, pos; | 298 unsigned int len; |
202 buffer * options_buf = NULL; | |
203 int line_num; | 299 int line_num; |
204 uid_t origuid; | 300 uid_t origuid; |
205 gid_t origgid; | 301 gid_t origgid; |
206 | 302 |
207 TRACE(("enter checkpubkey")) | 303 TRACE(("enter checkpubkey")) |
252 line = buf_new(MAX_AUTHKEYS_LINE); | 348 line = buf_new(MAX_AUTHKEYS_LINE); |
253 line_num = 0; | 349 line_num = 0; |
254 | 350 |
255 /* iterate through the lines */ | 351 /* iterate through the lines */ |
256 do { | 352 do { |
257 /* new line : potentially new options */ | |
258 if (options_buf) { | |
259 buf_free(options_buf); | |
260 options_buf = NULL; | |
261 } | |
262 | |
263 if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { | 353 if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { |
264 /* EOF reached */ | 354 /* EOF reached */ |
265 TRACE(("checkpubkey: authorized_keys EOF reached")) | 355 TRACE(("checkpubkey: authorized_keys EOF reached")) |
266 break; | 356 break; |
267 } | 357 } |
268 line_num++; | 358 line_num++; |
269 | 359 |
270 if (line->len < MIN_AUTHKEYS_LINE) { | 360 if (checkpubkey_line(line, line_num, filename, |
271 TRACE(("checkpubkey: line too short")) | 361 algo, algolen, keyblob, keybloblen) == DROPBEAR_SUCCESS) { |
272 continue; /* line is too short for it to be a valid key */ | |
273 } | |
274 | |
275 /* check the key type - will fail if there are options */ | |
276 TRACE(("a line!")) | |
277 | |
278 if (strncmp((const char *) buf_getptr(line, algolen), algo, algolen) != 0) { | |
279 int is_comment = 0; | |
280 unsigned char *options_start = NULL; | |
281 int options_len = 0; | |
282 int escape, quoted; | |
283 | |
284 /* skip over any comments or leading whitespace */ | |
285 while (line->pos < line->len) { | |
286 const char c = buf_getbyte(line); | |
287 if (c == ' ' || c == '\t') { | |
288 continue; | |
289 } else if (c == '#') { | |
290 is_comment = 1; | |
291 break; | |
292 } | |
293 buf_incrpos(line, -1); | |
294 break; | |
295 } | |
296 if (is_comment) { | |
297 /* next line */ | |
298 continue; | |
299 } | |
300 | |
301 /* remember start of options */ | |
302 options_start = buf_getptr(line, 1); | |
303 quoted = 0; | |
304 escape = 0; | |
305 options_len = 0; | |
306 | |
307 /* figure out where the options are */ | |
308 while (line->pos < line->len) { | |
309 const char c = buf_getbyte(line); | |
310 if (!quoted && (c == ' ' || c == '\t')) { | |
311 break; | |
312 } | |
313 escape = (!escape && c == '\\'); | |
314 if (!escape && c == '"') { | |
315 quoted = !quoted; | |
316 } | |
317 options_len++; | |
318 } | |
319 options_buf = buf_new(options_len); | |
320 buf_putbytes(options_buf, options_start, options_len); | |
321 | |
322 /* compare the algorithm. +3 so we have enough bytes to read a space and some base64 characters too. */ | |
323 if (line->pos + algolen+3 > line->len) { | |
324 continue; | |
325 } | |
326 if (strncmp((const char *) buf_getptr(line, algolen), algo, algolen) != 0) { | |
327 continue; | |
328 } | |
329 } | |
330 buf_incrpos(line, algolen); | |
331 | |
332 /* check for space (' ') character */ | |
333 if (buf_getbyte(line) != ' ') { | |
334 TRACE(("checkpubkey: space character expected, isn't there")) | |
335 continue; | |
336 } | |
337 | |
338 /* truncate the line at the space after the base64 data */ | |
339 pos = line->pos; | |
340 for (len = 0; line->pos < line->len; len++) { | |
341 if (buf_getbyte(line) == ' ') break; | |
342 } | |
343 buf_setpos(line, pos); | |
344 buf_setlen(line, line->pos + len); | |
345 | |
346 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)) | |
347 | |
348 ret = cmp_base64_key(keyblob, keybloblen, (const unsigned char *) algo, algolen, line, NULL); | |
349 | |
350 if (ret == DROPBEAR_SUCCESS && options_buf) { | |
351 ret = svr_add_pubkey_options(options_buf, line_num, filename); | |
352 } | |
353 | |
354 if (ret == DROPBEAR_SUCCESS) { | |
355 break; | 362 break; |
356 } | 363 } |
357 | 364 |
358 /* We continue to the next line otherwise */ | 365 /* We continue to the next line otherwise */ |
359 | 366 |
365 } | 372 } |
366 if (line) { | 373 if (line) { |
367 buf_free(line); | 374 buf_free(line); |
368 } | 375 } |
369 m_free(filename); | 376 m_free(filename); |
370 if (options_buf) { | |
371 buf_free(options_buf); | |
372 } | |
373 TRACE(("leave checkpubkey: ret=%d", ret)) | 377 TRACE(("leave checkpubkey: ret=%d", ret)) |
374 return ret; | 378 return ret; |
375 } | 379 } |
376 | 380 |
377 | 381 |
463 | 467 |
464 TRACE(("leave checkfileperm: success")) | 468 TRACE(("leave checkfileperm: success")) |
465 return DROPBEAR_SUCCESS; | 469 return DROPBEAR_SUCCESS; |
466 } | 470 } |
467 | 471 |
472 #ifdef DROPBEAR_FUZZ | |
473 int fuzz_checkpubkey_line(buffer* line, int line_num, char* filename, | |
474 const char* algo, unsigned int algolen, | |
475 const unsigned char* keyblob, unsigned int keybloblen) { | |
476 return checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen); | |
477 } | |
468 #endif | 478 #endif |
479 | |
480 #endif |