struct sshauthopt * sshauthopt_from_cert(struct sshkey *k) { struct sshauthopt *ret; if (k == NULL || !sshkey_type_is_cert(k->type) || k->cert == NULL || k->cert->type != SSH2_CERT_TYPE_USER) return NULL; if ((ret = sshauthopt_new()) == NULL) return NULL; /* Handle options and critical extensions separately */ if (cert_option_list(ret, k->cert->critical, OPTIONS_CRITICAL, 1) == -1) { sshauthopt_free(ret); return NULL; } if (cert_option_list(ret, k->cert->extensions, OPTIONS_EXTENSIONS, 0) == -1) { sshauthopt_free(ret); return NULL; } /* success */ return ret; }
/* Disable forwarding, etc for the session */ void auth_restrict_session(struct ssh *ssh) { struct sshauthopt *restricted; debug("%s: restricting session", __func__); /* A blank sshauthopt defaults to permitting nothing */ restricted = sshauthopt_new(); restricted->permit_pty_flag = 1; restricted->restricted = 1; if (auth_activate_options(ssh, restricted) != 0) fatal("%s: failed to restrict session", __func__); sshauthopt_free(restricted); }
struct sshauthopt * sshauthopt_new_with_keys_defaults(void) { struct sshauthopt *ret = NULL; if ((ret = sshauthopt_new()) == NULL) return NULL; /* Defaults for authorized_keys flags */ ret->permit_port_forwarding_flag = 1; ret->permit_agent_forwarding_flag = 1; ret->permit_x11_forwarding_flag = 1; ret->permit_pty_flag = 1; ret->permit_user_rc = 1; return ret; }
/* * Copy options */ struct sshauthopt * sshauthopt_copy(const struct sshauthopt *orig) { struct sshauthopt *ret; if ((ret = sshauthopt_new()) == NULL) return NULL; #define OPTSCALAR(x) ret->x = orig->x OPTSCALAR(permit_port_forwarding_flag); OPTSCALAR(permit_agent_forwarding_flag); OPTSCALAR(permit_x11_forwarding_flag); OPTSCALAR(permit_pty_flag); OPTSCALAR(permit_user_rc); OPTSCALAR(restricted); OPTSCALAR(cert_authority); OPTSCALAR(force_tun_device); OPTSCALAR(valid_before); #undef OPTSCALAR #define OPTSTRING(x) \ do { \ if (orig->x != NULL && (ret->x = strdup(orig->x)) == NULL) { \ sshauthopt_free(ret); \ return NULL; \ } \ } while (0) OPTSTRING(cert_principals); OPTSTRING(force_command); OPTSTRING(required_from_host_cert); OPTSTRING(required_from_host_keys); #undef OPTSTRING if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || dup_strings(&ret->permitopen, &ret->npermitopen, orig->permitopen, orig->npermitopen) != 0) { sshauthopt_free(ret); return NULL; } return ret; }
/* * Merges "additional" options to "primary" and returns the result. * NB. Some options from primary have primacy. */ struct sshauthopt * sshauthopt_merge(const struct sshauthopt *primary, const struct sshauthopt *additional, const char **errstrp) { struct sshauthopt *ret; const char *errstr = "internal error"; const char *tmp; if (errstrp != NULL) *errstrp = NULL; if ((ret = sshauthopt_new()) == NULL) goto alloc_fail; /* cert_authority and cert_principals are cleared in result */ /* Prefer access lists from primary. */ /* XXX err is both set and mismatch? */ tmp = primary->required_from_host_cert; if (tmp == NULL) tmp = additional->required_from_host_cert; if (tmp != NULL && (ret->required_from_host_cert = strdup(tmp)) == NULL) goto alloc_fail; tmp = primary->required_from_host_keys; if (tmp == NULL) tmp = additional->required_from_host_keys; if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) goto alloc_fail; /* force_tun_device, permitopen and environment prefer the primary. */ ret->force_tun_device = primary->force_tun_device; if (ret->force_tun_device == -1) ret->force_tun_device = additional->force_tun_device; if (primary->nenv > 0) { if (dup_strings(&ret->env, &ret->nenv, primary->env, primary->nenv) != 0) goto alloc_fail; } else if (additional->nenv) { if (dup_strings(&ret->env, &ret->nenv, additional->env, additional->nenv) != 0) goto alloc_fail; } if (primary->npermitopen > 0) { if (dup_strings(&ret->permitopen, &ret->npermitopen, primary->permitopen, primary->npermitopen) != 0) goto alloc_fail; } else if (additional->npermitopen > 0) { if (dup_strings(&ret->permitopen, &ret->npermitopen, additional->permitopen, additional->npermitopen) != 0) goto alloc_fail; } /* Flags are logical-AND (i.e. must be set in both for permission) */ #define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) OPTFLAG(permit_port_forwarding_flag); OPTFLAG(permit_agent_forwarding_flag); OPTFLAG(permit_x11_forwarding_flag); OPTFLAG(permit_pty_flag); OPTFLAG(permit_user_rc); #undef OPTFLAG /* Earliest expiry time should win */ if (primary->valid_before != 0) ret->valid_before = primary->valid_before; if (additional->valid_before != 0 && additional->valid_before < ret->valid_before) ret->valid_before = additional->valid_before; /* * When both multiple forced-command are specified, only * proceed if they are identical, otherwise fail. */ if (primary->force_command != NULL && additional->force_command != NULL) { if (strcmp(primary->force_command, additional->force_command) == 0) { /* ok */ ret->force_command = strdup(primary->force_command); if (ret->force_command == NULL) goto alloc_fail; } else { errstr = "forced command options do not match"; goto fail; } } else if (primary->force_command != NULL) { if ((ret->force_command = strdup( primary->force_command)) == NULL) goto alloc_fail; } else if (additional->force_command != NULL) { if ((ret->force_command = strdup( additional->force_command)) == NULL) goto alloc_fail; } /* success */ if (errstrp != NULL) *errstrp = NULL; return ret; alloc_fail: errstr = "memory allocation failed"; fail: if (errstrp != NULL) *errstrp = errstr; sshauthopt_free(ret); return NULL; }