Mercurial > dropbear
comparison svr-authpubkey.c @ 476:df7f7da7f6e4 pubkey-options
- Rework pubkey options to be more careful about buffer lengths. Needs review.
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 12 Sep 2008 17:23:56 +0000 |
parents | 52a644e7b8e1 |
children | a98a2138364a |
comparison
equal
deleted
inserted
replaced
475:52a644e7b8e1 | 476:df7f7da7f6e4 |
---|---|
187 | 187 |
188 FILE * authfile = NULL; | 188 FILE * authfile = NULL; |
189 char * filename = NULL; | 189 char * filename = NULL; |
190 int ret = DROPBEAR_FAILURE; | 190 int ret = DROPBEAR_FAILURE; |
191 buffer * line = NULL; | 191 buffer * line = NULL; |
192 unsigned int len, pos, quoted; | 192 unsigned int len, pos; |
193 const char *options = NULL; | 193 buffer * options_buf = NULL; |
194 int line_num; | |
194 | 195 |
195 TRACE(("enter checkpubkey")) | 196 TRACE(("enter checkpubkey")) |
196 | 197 |
197 /* check that we can use the algo */ | 198 /* check that we can use the algo */ |
198 if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) { | 199 if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) { |
223 goto out; | 224 goto out; |
224 } | 225 } |
225 TRACE(("checkpubkey: opened authorized_keys OK")) | 226 TRACE(("checkpubkey: opened authorized_keys OK")) |
226 | 227 |
227 line = buf_new(MAX_AUTHKEYS_LINE); | 228 line = buf_new(MAX_AUTHKEYS_LINE); |
229 line_num = 0; | |
228 | 230 |
229 /* iterate through the lines */ | 231 /* iterate through the lines */ |
230 do { | 232 do { |
231 /* new line : potentially new options */ | 233 /* new line : potentially new options */ |
232 options = NULL; | 234 if (options_buf) { |
235 buf_free(options_buf); | |
236 options_buf = NULL; | |
237 } | |
233 | 238 |
234 if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { | 239 if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { |
235 /* EOF reached */ | 240 /* EOF reached */ |
236 TRACE(("checkpubkey: authorized_keys EOF reached")) | 241 TRACE(("checkpubkey: authorized_keys EOF reached")) |
237 break; | 242 break; |
238 } | 243 } |
244 line_num++; | |
239 | 245 |
240 if (line->len < MIN_AUTHKEYS_LINE) { | 246 if (line->len < MIN_AUTHKEYS_LINE) { |
241 TRACE(("checkpubkey: line too short")) | 247 TRACE(("checkpubkey: line too short")) |
242 continue; /* line is too short for it to be a valid key */ | 248 continue; /* line is too short for it to be a valid key */ |
243 } | 249 } |
244 | 250 |
245 /* check the key type - will fail if there are options */ | 251 /* check the key type - will fail if there are options */ |
252 TRACE(("a line!")) | |
253 | |
246 if (strncmp(buf_getptr(line, algolen), algo, algolen) != 0) { | 254 if (strncmp(buf_getptr(line, algolen), algo, algolen) != 0) { |
247 /* there may be options or a commented line */ | 255 int is_comment = 0; |
248 if ('#' == line->data[line->pos]) continue; | 256 char *options_start = NULL; |
249 /* no comment, skip to next space character */ | 257 int options_len = 0; |
250 len = 0; | 258 int escape, quoted; |
251 pos = line->pos; | 259 |
252 options = buf_getptr(line, 1); | 260 /* skip over any comments or leading whitespace */ |
261 while (line->pos < line->len) { | |
262 const char c = buf_getbyte(line); | |
263 if (c == ' ' || c == '\t') { | |
264 continue; | |
265 } else if (c == '#') { | |
266 is_comment = 1; | |
267 break; | |
268 } | |
269 buf_incrpos(line, -1); | |
270 break; | |
271 } | |
272 if (is_comment) { | |
273 /* next line */ | |
274 continue; | |
275 } | |
276 | |
277 /* remember start of options */ | |
278 options_start = buf_getptr(line, 1); | |
253 quoted = 0; | 279 quoted = 0; |
254 while (line->data[pos] | 280 escape = 0; |
255 && (quoted || (line->data[pos] != ' ' | 281 options_len = 0; |
256 && line->data[pos] != '\t' | 282 |
257 && line->data[pos] != '\n' | 283 /* figure out where the options are */ |
258 && line->data[pos] != '\r'))) { | 284 while (line->pos < line->len) { |
259 pos++; | 285 const char c = buf_getbyte(line); |
260 if (line->data[pos] == '\\' | 286 if (!quoted && (c == ' ' || c == '\t')) { |
261 && line->data[pos+1] == '"') { | 287 break; |
262 pos++; /* skip both */ | 288 } |
263 } else if (line->data[pos] == '"') | 289 escape = (!escape && c == '\\'); |
264 quoted = !quoted; | 290 if (!escape && c == '"') { |
265 } /* line->data[pos] == ['\0'|' '|'\t'] */ | 291 quoted = !quoted; |
266 | 292 } |
267 /* skip line if there is nothing left */ | 293 options_len++; |
268 if (pos >= line->len) continue; | 294 } |
269 /* skip line if it begins with a space or tab character */ | 295 options_buf = buf_new(options_len); |
270 if (pos == line->pos) continue; | 296 buf_putbytes(options_buf, options_start, options_len); |
271 /* set the position of the line after what we have read */ | 297 |
272 buf_setpos(line, pos+1); | 298 /* compare the algorithm */ |
273 /* give a second chance to the algo */ | 299 if (line->pos + algolen > line->len) { |
274 if (line->pos + algolen > line->len) continue; | 300 continue; |
301 } | |
275 if (strncmp(buf_getptr(line, algolen), algo, algolen) != 0) { | 302 if (strncmp(buf_getptr(line, algolen), algo, algolen) != 0) { |
276 continue; | 303 continue; |
277 } | 304 } |
278 } | 305 } |
279 buf_incrpos(line, algolen); | 306 buf_incrpos(line, algolen); |
280 | 307 |
281 /* check for space (' ') character */ | 308 /* check for space (' ') character */ |
282 if (buf_getbyte(line) != ' ') { | 309 if (buf_getbyte(line) != ' ') { |
294 | 321 |
295 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)) | 322 TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)) |
296 | 323 |
297 ret = cmp_base64_key(keyblob, keybloblen, algo, algolen, line, NULL); | 324 ret = cmp_base64_key(keyblob, keybloblen, algo, algolen, line, NULL); |
298 | 325 |
299 if (ret == DROPBEAR_SUCCESS) { | 326 if (ret == DROPBEAR_SUCCESS && options_buf) { |
300 ret = svr_add_pubkey_options(options); | 327 ret = svr_add_pubkey_options(options_buf, line_num, filename); |
301 } | 328 } |
302 | 329 |
303 if (ret == DROPBEAR_SUCCESS) { | 330 if (ret == DROPBEAR_SUCCESS) { |
304 break; | 331 break; |
305 } | 332 } |
314 } | 341 } |
315 if (line) { | 342 if (line) { |
316 buf_free(line); | 343 buf_free(line); |
317 } | 344 } |
318 m_free(filename); | 345 m_free(filename); |
346 if (options_buf) { | |
347 buf_free(options_buf); | |
348 } | |
319 TRACE(("leave checkpubkey: ret=%d", ret)) | 349 TRACE(("leave checkpubkey: ret=%d", ret)) |
320 return ret; | 350 return ret; |
321 } | 351 } |
322 | 352 |
323 | 353 |