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