Branch data Line data Source code
1 : : /* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */
2 : : /*
3 : : * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 : : * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 : : * All rights reserved
6 : : * As far as I am concerned, the code I have written for this software
7 : : * can be used freely for any purpose. Any derived versions of this
8 : : * software must be clearly marked as such, and if the derived work is
9 : : * incompatible with the protocol description in the RFC file, it must be
10 : : * called by a name other than "ssh" or "Secure Shell".
11 : : */
12 : :
13 : : #include "includes.h"
14 : :
15 : : #include <sys/types.h>
16 : :
17 : : #include <netdb.h>
18 : : #include <pwd.h>
19 : : #include <string.h>
20 : : #include <stdio.h>
21 : : #include <stdarg.h>
22 : :
23 : : #include "openbsd-compat/sys-queue.h"
24 : : #include "xmalloc.h"
25 : : #include "match.h"
26 : : #include "log.h"
27 : : #include "canohost.h"
28 : : #include "buffer.h"
29 : : #include "channels.h"
30 : : #include "servconf.h"
31 : : #include "misc.h"
32 : : #include "key.h"
33 : : #include "auth-options.h"
34 : : #include "hostfile.h"
35 : : #include "auth.h"
36 : :
37 : : /* Flags set authorized_keys flags */
38 : : int no_port_forwarding_flag = 0;
39 : : int no_agent_forwarding_flag = 0;
40 : : int no_x11_forwarding_flag = 0;
41 : : int no_pty_flag = 0;
42 : : int no_user_rc = 0;
43 : : int key_is_cert_authority = 0;
44 : :
45 : : /* "command=" option. */
46 : : char *forced_command = NULL;
47 : :
48 : : /* "environment=" options. */
49 : : struct envstring *custom_environment = NULL;
50 : :
51 : : /* "tunnel=" option. */
52 : : int forced_tun_device = -1;
53 : :
54 : : /* "principals=" option. */
55 : : char *authorized_principals = NULL;
56 : :
57 : : extern ServerOptions options;
58 : :
59 : : void
60 : 5341 : auth_clear_options(void)
61 : : {
62 : 5341 : no_agent_forwarding_flag = 0;
63 : 5341 : no_port_forwarding_flag = 0;
64 : 5341 : no_pty_flag = 0;
65 : 5341 : no_x11_forwarding_flag = 0;
66 : 5341 : no_user_rc = 0;
67 : 5341 : key_is_cert_authority = 0;
68 [ + + ]: 5342 : while (custom_environment) {
69 : 1 : struct envstring *ce = custom_environment;
70 : 1 : custom_environment = ce->next;
71 : 1 : free(ce->s);
72 : 1 : free(ce);
73 : : }
74 [ + + ]: 5341 : if (forced_command) {
75 : 64 : free(forced_command);
76 : 64 : forced_command = NULL;
77 : : }
78 [ + + ]: 5341 : if (authorized_principals) {
79 : 18 : free(authorized_principals);
80 : 18 : authorized_principals = NULL;
81 : : }
82 : 5341 : forced_tun_device = -1;
83 : 5341 : channel_clear_permitted_opens();
84 : 5341 : }
85 : :
86 : : /*
87 : : * return 1 if access is granted, 0 if not.
88 : : * side effect: sets key option flags
89 : : */
90 : : int
91 : 1492 : auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
92 : : {
93 : : const char *cp;
94 : : int i;
95 : :
96 : : /* reset options */
97 : 1492 : auth_clear_options();
98 : :
99 [ + + ]: 1492 : if (!opts)
100 : : return 1;
101 : :
102 [ + - ][ + - ]: 376 : while (*opts && *opts != ' ' && *opts != '\t') {
103 : 376 : cp = "cert-authority";
104 [ + + ]: 376 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
105 : 116 : key_is_cert_authority = 1;
106 : 116 : opts += strlen(cp);
107 : 116 : goto next_option;
108 : : }
109 : 260 : cp = "no-port-forwarding";
110 [ - + ]: 260 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
111 : 0 : auth_debug_add("Port forwarding disabled.");
112 : 0 : no_port_forwarding_flag = 1;
113 : 0 : opts += strlen(cp);
114 : 0 : goto next_option;
115 : : }
116 : 260 : cp = "no-agent-forwarding";
117 [ - + ]: 260 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
118 : 0 : auth_debug_add("Agent forwarding disabled.");
119 : 0 : no_agent_forwarding_flag = 1;
120 : 0 : opts += strlen(cp);
121 : 0 : goto next_option;
122 : : }
123 : 260 : cp = "no-X11-forwarding";
124 [ - + ]: 260 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
125 : 0 : auth_debug_add("X11 forwarding disabled.");
126 : 0 : no_x11_forwarding_flag = 1;
127 : 0 : opts += strlen(cp);
128 : 0 : goto next_option;
129 : : }
130 : 260 : cp = "no-pty";
131 [ + + ]: 260 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
132 : 6 : auth_debug_add("Pty allocation disabled.");
133 : 6 : no_pty_flag = 1;
134 : 6 : opts += strlen(cp);
135 : 6 : goto next_option;
136 : : }
137 : 254 : cp = "no-user-rc";
138 [ - + ]: 254 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
139 : 0 : auth_debug_add("User rc file execution disabled.");
140 : 0 : no_user_rc = 1;
141 : 0 : opts += strlen(cp);
142 : 0 : goto next_option;
143 : : }
144 : 254 : cp = "command=\"";
145 [ + + ]: 254 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
146 : 79 : opts += strlen(cp);
147 [ - + ]: 79 : if (forced_command != NULL)
148 : 0 : free(forced_command);
149 : 79 : forced_command = xmalloc(strlen(opts) + 1);
150 : 79 : i = 0;
151 [ + - ]: 457 : while (*opts) {
152 [ + + ]: 457 : if (*opts == '"')
153 : : break;
154 [ - + ][ # # ]: 378 : if (*opts == '\\' && opts[1] == '"') {
155 : 0 : opts += 2;
156 : 0 : forced_command[i++] = '"';
157 : 0 : continue;
158 : : }
159 : 378 : forced_command[i++] = *opts++;
160 : : }
161 [ - + ]: 79 : if (!*opts) {
162 : 0 : debug("%.100s, line %lu: missing end quote",
163 : : file, linenum);
164 : 0 : auth_debug_add("%.100s, line %lu: missing end quote",
165 : : file, linenum);
166 : 0 : free(forced_command);
167 : 0 : forced_command = NULL;
168 : 0 : goto bad_option;
169 : : }
170 : 79 : forced_command[i] = '\0';
171 : 79 : auth_debug_add("Forced command.");
172 : 79 : opts++;
173 : 79 : goto next_option;
174 : : }
175 : 175 : cp = "principals=\"";
176 [ + + ]: 175 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
177 : 36 : opts += strlen(cp);
178 [ - + ]: 36 : if (authorized_principals != NULL)
179 : 0 : free(authorized_principals);
180 : 36 : authorized_principals = xmalloc(strlen(opts) + 1);
181 : 36 : i = 0;
182 [ + - ]: 540 : while (*opts) {
183 [ + + ]: 540 : if (*opts == '"')
184 : : break;
185 [ - + ][ # # ]: 504 : if (*opts == '\\' && opts[1] == '"') {
186 : 0 : opts += 2;
187 : 0 : authorized_principals[i++] = '"';
188 : 0 : continue;
189 : : }
190 : 504 : authorized_principals[i++] = *opts++;
191 : : }
192 [ - + ]: 36 : if (!*opts) {
193 : 0 : debug("%.100s, line %lu: missing end quote",
194 : : file, linenum);
195 : 0 : auth_debug_add("%.100s, line %lu: missing end quote",
196 : : file, linenum);
197 : 0 : free(authorized_principals);
198 : 0 : authorized_principals = NULL;
199 : 0 : goto bad_option;
200 : : }
201 : 36 : authorized_principals[i] = '\0';
202 : 36 : auth_debug_add("principals: %.900s",
203 : : authorized_principals);
204 : 36 : opts++;
205 : 36 : goto next_option;
206 : : }
207 : 139 : cp = "environment=\"";
208 [ + + ][ + - ]: 139 : if (options.permit_user_env &&
209 : 3 : strncasecmp(opts, cp, strlen(cp)) == 0) {
210 : : char *s;
211 : : struct envstring *new_envstring;
212 : :
213 : 3 : opts += strlen(cp);
214 : 3 : s = xmalloc(strlen(opts) + 1);
215 : 3 : i = 0;
216 [ + - ]: 24 : while (*opts) {
217 [ + + ]: 24 : if (*opts == '"')
218 : : break;
219 [ - + ][ # # ]: 21 : if (*opts == '\\' && opts[1] == '"') {
220 : 0 : opts += 2;
221 : 0 : s[i++] = '"';
222 : 0 : continue;
223 : : }
224 : 21 : s[i++] = *opts++;
225 : : }
226 [ - + ]: 3 : if (!*opts) {
227 : 0 : debug("%.100s, line %lu: missing end quote",
228 : : file, linenum);
229 : 0 : auth_debug_add("%.100s, line %lu: missing end quote",
230 : : file, linenum);
231 : 0 : free(s);
232 : 0 : goto bad_option;
233 : : }
234 : 3 : s[i] = '\0';
235 : 3 : auth_debug_add("Adding to environment: %.900s", s);
236 : 3 : debug("Adding to environment: %.900s", s);
237 : 3 : opts++;
238 : 3 : new_envstring = xcalloc(1, sizeof(struct envstring));
239 : 3 : new_envstring->s = s;
240 : 3 : new_envstring->next = custom_environment;
241 : 3 : custom_environment = new_envstring;
242 : 3 : goto next_option;
243 : : }
244 : 136 : cp = "from=\"";
245 [ + + ]: 136 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
246 : 6 : const char *remote_ip = get_remote_ipaddr();
247 : 6 : const char *remote_host = get_canonical_hostname(
248 : : options.use_dns);
249 : 6 : char *patterns = xmalloc(strlen(opts) + 1);
250 : :
251 : 6 : opts += strlen(cp);
252 : 6 : i = 0;
253 [ + - ]: 66 : while (*opts) {
254 [ + + ]: 66 : if (*opts == '"')
255 : : break;
256 [ - + ][ # # ]: 60 : if (*opts == '\\' && opts[1] == '"') {
257 : 0 : opts += 2;
258 : 0 : patterns[i++] = '"';
259 : 0 : continue;
260 : : }
261 : 60 : patterns[i++] = *opts++;
262 : : }
263 [ - + ]: 6 : if (!*opts) {
264 : 0 : debug("%.100s, line %lu: missing end quote",
265 : : file, linenum);
266 : 0 : auth_debug_add("%.100s, line %lu: missing end quote",
267 : : file, linenum);
268 : 0 : free(patterns);
269 : 0 : goto bad_option;
270 : : }
271 : 6 : patterns[i] = '\0';
272 : 6 : opts++;
273 [ + - - - ]: 6 : switch (match_host_and_ip(remote_host, remote_ip,
274 : : patterns)) {
275 : : case 1:
276 : 6 : free(patterns);
277 : : /* Host name matches. */
278 : 6 : goto next_option;
279 : : case -1:
280 : 0 : debug("%.100s, line %lu: invalid criteria",
281 : : file, linenum);
282 : 0 : auth_debug_add("%.100s, line %lu: "
283 : : "invalid criteria", file, linenum);
284 : : /* FALLTHROUGH */
285 : : case 0:
286 : 0 : free(patterns);
287 : 0 : logit("Authentication tried for %.100s with "
288 : : "correct key but not from a permitted "
289 : : "host (host=%.200s, ip=%.200s).",
290 : : pw->pw_name, remote_host, remote_ip);
291 : 0 : auth_debug_add("Your host '%.200s' is not "
292 : : "permitted to use this key for login.",
293 : : remote_host);
294 : 0 : break;
295 : : }
296 : : /* deny access */
297 : : return 0;
298 : : }
299 : 130 : cp = "permitopen=\"";
300 [ + - ]: 130 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
301 : : char *host, *p;
302 : : int port;
303 : 130 : char *patterns = xmalloc(strlen(opts) + 1);
304 : :
305 : 130 : opts += strlen(cp);
306 : 130 : i = 0;
307 [ + - ]: 1806 : while (*opts) {
308 [ + + ]: 1806 : if (*opts == '"')
309 : : break;
310 [ - + ][ # # ]: 1676 : if (*opts == '\\' && opts[1] == '"') {
311 : 0 : opts += 2;
312 : 0 : patterns[i++] = '"';
313 : 0 : continue;
314 : : }
315 : 1676 : patterns[i++] = *opts++;
316 : : }
317 [ - + ]: 130 : if (!*opts) {
318 : 0 : debug("%.100s, line %lu: missing end quote",
319 : : file, linenum);
320 : 0 : auth_debug_add("%.100s, line %lu: missing "
321 : : "end quote", file, linenum);
322 : 0 : free(patterns);
323 : 0 : goto bad_option;
324 : : }
325 : 130 : patterns[i] = '\0';
326 : 130 : opts++;
327 : 130 : p = patterns;
328 : 130 : host = hpdelim(&p);
329 [ + - ][ - + ]: 130 : if (host == NULL || strlen(host) >= NI_MAXHOST) {
330 : 0 : debug("%.100s, line %lu: Bad permitopen "
331 : : "specification <%.100s>", file, linenum,
332 : : patterns);
333 : 0 : auth_debug_add("%.100s, line %lu: "
334 : : "Bad permitopen specification", file,
335 : : linenum);
336 : 0 : free(patterns);
337 : 0 : goto bad_option;
338 : : }
339 : 130 : host = cleanhostname(host);
340 [ + - ][ - + ]: 130 : if (p == NULL || (port = permitopen_port(p)) < 0) {
341 [ # # ]: 0 : debug("%.100s, line %lu: Bad permitopen port "
342 : 0 : "<%.100s>", file, linenum, p ? p : "");
343 : 0 : auth_debug_add("%.100s, line %lu: "
344 : : "Bad permitopen port", file, linenum);
345 : 0 : free(patterns);
346 : 0 : goto bad_option;
347 : : }
348 [ + + ]: 130 : if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
349 : 94 : channel_add_permitted_opens(host, port);
350 : 130 : free(patterns);
351 : 130 : goto next_option;
352 : : }
353 : 0 : cp = "tunnel=\"";
354 [ # # ]: 0 : if (strncasecmp(opts, cp, strlen(cp)) == 0) {
355 : 0 : char *tun = NULL;
356 : 0 : opts += strlen(cp);
357 : 0 : tun = xmalloc(strlen(opts) + 1);
358 : 0 : i = 0;
359 [ # # ]: 0 : while (*opts) {
360 [ # # ]: 0 : if (*opts == '"')
361 : : break;
362 : 0 : tun[i++] = *opts++;
363 : : }
364 [ # # ]: 0 : if (!*opts) {
365 : 0 : debug("%.100s, line %lu: missing end quote",
366 : : file, linenum);
367 : 0 : auth_debug_add("%.100s, line %lu: missing end quote",
368 : : file, linenum);
369 : 0 : free(tun);
370 : 0 : forced_tun_device = -1;
371 : 0 : goto bad_option;
372 : : }
373 : 0 : tun[i] = '\0';
374 : 0 : forced_tun_device = a2tun(tun, NULL);
375 : 0 : free(tun);
376 [ # # ]: 0 : if (forced_tun_device == SSH_TUNID_ERR) {
377 : 0 : debug("%.100s, line %lu: invalid tun device",
378 : : file, linenum);
379 : 0 : auth_debug_add("%.100s, line %lu: invalid tun device",
380 : : file, linenum);
381 : 0 : forced_tun_device = -1;
382 : 0 : goto bad_option;
383 : : }
384 : 0 : auth_debug_add("Forced tun device: %d", forced_tun_device);
385 : 0 : opts++;
386 : 0 : goto next_option;
387 : : }
388 : : next_option:
389 : : /*
390 : : * Skip the comma, and move to the next option
391 : : * (or break out if there are no more).
392 : : */
393 [ - + ]: 376 : if (!*opts)
394 : 0 : fatal("Bugs in auth-options.c option processing.");
395 [ + + ]: 376 : if (*opts == ' ' || *opts == '\t')
396 : : break; /* End of options. */
397 [ + - ]: 79 : if (*opts != ',')
398 : : goto bad_option;
399 : 79 : opts++;
400 : : /* Process the next option. */
401 : : }
402 : :
403 : : /* grant access */
404 : : return 1;
405 : :
406 : : bad_option:
407 : 0 : logit("Bad options in %.100s file, line %lu: %.50s",
408 : : file, linenum, opts);
409 : 0 : auth_debug_add("Bad options in %.100s file, line %lu: %.50s",
410 : : file, linenum, opts);
411 : :
412 : : /* deny access */
413 : 0 : return 0;
414 : : }
415 : :
416 : : #define OPTIONS_CRITICAL 1
417 : : #define OPTIONS_EXTENSIONS 2
418 : : static int
419 : 502 : parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
420 : : u_int which, int crit,
421 : : int *cert_no_port_forwarding_flag,
422 : : int *cert_no_agent_forwarding_flag,
423 : : int *cert_no_x11_forwarding_flag,
424 : : int *cert_no_pty_flag,
425 : : int *cert_no_user_rc,
426 : : char **cert_forced_command,
427 : : int *cert_source_address_done)
428 : : {
429 : : char *command, *allowed;
430 : : const char *remote_ip;
431 : 502 : char *name = NULL;
432 : 502 : u_char *data_blob = NULL;
433 : : u_int nlen, dlen, clen;
434 : : Buffer c, data;
435 : 502 : int ret = -1, result, found;
436 : :
437 : 502 : buffer_init(&data);
438 : :
439 : : /* Make copy to avoid altering original */
440 : 502 : buffer_init(&c);
441 : 502 : buffer_append(&c, optblob, optblob_len);
442 : :
443 [ + + ]: 1970 : while (buffer_len(&c) > 0) {
444 [ + - ][ - + ]: 1468 : if ((name = buffer_get_cstring_ret(&c, &nlen)) == NULL ||
445 : : (data_blob = buffer_get_string_ret(&c, &dlen)) == NULL) {
446 : 0 : error("Certificate options corrupt");
447 : : goto out;
448 : : }
449 : 1468 : buffer_append(&data, data_blob, dlen);
450 : 1468 : debug3("found certificate option \"%.100s\" len %u",
451 : : name, dlen);
452 : 1468 : found = 0;
453 [ + + ]: 1468 : if ((which & OPTIONS_EXTENSIONS) != 0) {
454 [ + + ]: 1464 : if (strcmp(name, "permit-X11-forwarding") == 0) {
455 : 292 : *cert_no_x11_forwarding_flag = 0;
456 : 292 : found = 1;
457 [ + + ]: 1172 : } else if (strcmp(name,
458 : : "permit-agent-forwarding") == 0) {
459 : 292 : *cert_no_agent_forwarding_flag = 0;
460 : 292 : found = 1;
461 [ + + ]: 880 : } else if (strcmp(name,
462 : : "permit-port-forwarding") == 0) {
463 : 292 : *cert_no_port_forwarding_flag = 0;
464 : 292 : found = 1;
465 [ + + ]: 588 : } else if (strcmp(name, "permit-pty") == 0) {
466 : 292 : *cert_no_pty_flag = 0;
467 : 292 : found = 1;
468 [ + + ]: 296 : } else if (strcmp(name, "permit-user-rc") == 0) {
469 : 292 : *cert_no_user_rc = 0;
470 : 292 : found = 1;
471 : : }
472 : : }
473 [ + + ][ + - ]: 1468 : if (!found && (which & OPTIONS_CRITICAL) != 0) {
474 [ + - ]: 8 : if (strcmp(name, "force-command") == 0) {
475 [ - + ]: 8 : if ((command = buffer_get_cstring_ret(&data,
476 : : &clen)) == NULL) {
477 : 0 : error("Certificate constraint \"%s\" "
478 : : "corrupt", name);
479 : : goto out;
480 : : }
481 [ - + ]: 8 : if (*cert_forced_command != NULL) {
482 : 0 : error("Certificate has multiple "
483 : : "force-command options");
484 : 0 : free(command);
485 : : goto out;
486 : : }
487 : 8 : *cert_forced_command = command;
488 : 8 : found = 1;
489 : : }
490 [ - + ]: 8 : if (strcmp(name, "source-address") == 0) {
491 [ # # ]: 0 : if ((allowed = buffer_get_cstring_ret(&data,
492 : : &clen)) == NULL) {
493 : 0 : error("Certificate constraint "
494 : : "\"%s\" corrupt", name);
495 : : goto out;
496 : : }
497 [ # # ]: 0 : if ((*cert_source_address_done)++) {
498 : 0 : error("Certificate has multiple "
499 : : "source-address options");
500 : 0 : free(allowed);
501 : : goto out;
502 : : }
503 : 0 : remote_ip = get_remote_ipaddr();
504 : 0 : result = addr_match_cidr_list(remote_ip,
505 : : allowed);
506 : 0 : free(allowed);
507 [ # # # ]: 0 : switch (result) {
508 : : case 1:
509 : : /* accepted */
510 : : break;
511 : : case 0:
512 : : /* no match */
513 : 0 : logit("Authentication tried for %.100s "
514 : : "with valid certificate but not "
515 : : "from a permitted host "
516 : : "(ip=%.200s).", pw->pw_name,
517 : : remote_ip);
518 : 0 : auth_debug_add("Your address '%.200s' "
519 : : "is not permitted to use this "
520 : : "certificate for login.",
521 : : remote_ip);
522 : : goto out;
523 : : case -1:
524 : : default:
525 : 0 : error("Certificate source-address "
526 : : "contents invalid");
527 : : goto out;
528 : : }
529 : : found = 1;
530 : : }
531 : : }
532 : :
533 [ - + ]: 1468 : if (!found) {
534 [ # # ]: 0 : if (crit) {
535 : 0 : error("Certificate critical option \"%s\" "
536 : : "is not supported", name);
537 : : goto out;
538 : : } else {
539 : 0 : logit("Certificate extension \"%s\" "
540 : : "is not supported", name);
541 : : }
542 [ - + ]: 1468 : } else if (buffer_len(&data) != 0) {
543 : 0 : error("Certificate option \"%s\" corrupt "
544 : : "(extra data)", name);
545 : : goto out;
546 : : }
547 : 1468 : buffer_clear(&data);
548 : 1468 : free(name);
549 : 1468 : free(data_blob);
550 : 1468 : name = NULL;
551 : 1468 : data_blob = NULL;
552 : : }
553 : : /* successfully parsed all options */
554 : : ret = 0;
555 : :
556 : : out:
557 [ - + ]: 502 : if (ret != 0 &&
558 [ # # ]: 0 : cert_forced_command != NULL &&
559 : 0 : *cert_forced_command != NULL) {
560 : 0 : free(*cert_forced_command);
561 : 0 : *cert_forced_command = NULL;
562 : : }
563 [ - + ]: 502 : if (name != NULL)
564 : 0 : free(name);
565 [ - + ]: 502 : if (data_blob != NULL)
566 : 0 : free(data_blob);
567 : 502 : buffer_free(&data);
568 : 502 : buffer_free(&c);
569 : 502 : return ret;
570 : : }
571 : :
572 : : /*
573 : : * Set options from critical certificate options. These supersede user key
574 : : * options so this must be called after auth_parse_options().
575 : : */
576 : : int
577 : 292 : auth_cert_options(Key *k, struct passwd *pw)
578 : : {
579 : 292 : int cert_no_port_forwarding_flag = 1;
580 : 292 : int cert_no_agent_forwarding_flag = 1;
581 : 292 : int cert_no_x11_forwarding_flag = 1;
582 : 292 : int cert_no_pty_flag = 1;
583 : 292 : int cert_no_user_rc = 1;
584 : 292 : char *cert_forced_command = NULL;
585 : 292 : int cert_source_address_done = 0;
586 : :
587 [ + + ]: 292 : if (key_cert_is_legacy(k)) {
588 : : /* All options are in the one field for v00 certs */
589 [ + - ]: 82 : if (parse_option_list(buffer_ptr(&k->cert->critical),
590 : 82 : buffer_len(&k->cert->critical), pw,
591 : : OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
592 : : &cert_no_port_forwarding_flag,
593 : : &cert_no_agent_forwarding_flag,
594 : : &cert_no_x11_forwarding_flag,
595 : : &cert_no_pty_flag,
596 : : &cert_no_user_rc,
597 : : &cert_forced_command,
598 : : &cert_source_address_done) == -1)
599 : : return -1;
600 : : } else {
601 : : /* Separate options and extensions for v01 certs */
602 [ + - ]: 210 : if (parse_option_list(buffer_ptr(&k->cert->critical),
603 : 210 : buffer_len(&k->cert->critical), pw,
604 : : OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
605 : : &cert_forced_command,
606 : : &cert_source_address_done) == -1)
607 : : return -1;
608 [ + - ]: 210 : if (parse_option_list(buffer_ptr(&k->cert->extensions),
609 : 210 : buffer_len(&k->cert->extensions), pw,
610 : : OPTIONS_EXTENSIONS, 1,
611 : : &cert_no_port_forwarding_flag,
612 : : &cert_no_agent_forwarding_flag,
613 : : &cert_no_x11_forwarding_flag,
614 : : &cert_no_pty_flag,
615 : : &cert_no_user_rc,
616 : : NULL, NULL) == -1)
617 : : return -1;
618 : : }
619 : :
620 : 292 : no_port_forwarding_flag |= cert_no_port_forwarding_flag;
621 : 292 : no_agent_forwarding_flag |= cert_no_agent_forwarding_flag;
622 : 292 : no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
623 : 292 : no_pty_flag |= cert_no_pty_flag;
624 : 292 : no_user_rc |= cert_no_user_rc;
625 : : /* CA-specified forced command supersedes key option */
626 [ + + ]: 292 : if (cert_forced_command != NULL) {
627 [ + + ]: 8 : if (forced_command != NULL)
628 : 2 : free(forced_command);
629 : 8 : forced_command = cert_forced_command;
630 : : }
631 : : return 0;
632 : : }
633 : :
|