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