You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
517 lines
18 KiB
517 lines
18 KiB
diff -up openssh-7.4p1/auth2.c.expose-pam openssh-7.4p1/auth2.c |
|
--- openssh-7.4p1/auth2.c.expose-pam 2016-12-23 15:40:26.768447868 +0100 |
|
+++ openssh-7.4p1/auth2.c 2016-12-23 15:40:26.818447876 +0100 |
|
@@ -310,6 +310,7 @@ userauth_finish(Authctxt *authctxt, int |
|
const char *submethod) |
|
{ |
|
char *methods; |
|
+ char *prev_auth_details; |
|
int partial = 0; |
|
|
|
if (!authctxt->valid && authenticated) |
|
@@ -340,6 +341,18 @@ userauth_finish(Authctxt *authctxt, int |
|
if (authctxt->postponed) |
|
return; |
|
|
|
+ if (authenticated || partial) { |
|
+ prev_auth_details = authctxt->auth_details; |
|
+ xasprintf(&authctxt->auth_details, "%s%s%s%s%s", |
|
+ prev_auth_details ? prev_auth_details : "", |
|
+ prev_auth_details ? ", " : "", method, |
|
+ authctxt->last_details ? ": " : "", |
|
+ authctxt->last_details ? authctxt->last_details : ""); |
|
+ free(prev_auth_details); |
|
+ } |
|
+ free(authctxt->last_details); |
|
+ authctxt->last_details = NULL; |
|
+ |
|
#ifdef USE_PAM |
|
if (options.use_pam && authenticated) { |
|
if (!PRIVSEP(do_pam_account())) { |
|
diff -up openssh-7.4p1/auth2-gss.c.expose-pam openssh-7.4p1/auth2-gss.c |
|
--- openssh-7.4p1/auth2-gss.c.expose-pam 2016-12-23 15:40:26.769447868 +0100 |
|
+++ openssh-7.4p1/auth2-gss.c 2016-12-23 15:40:26.818447876 +0100 |
|
@@ -276,6 +276,9 @@ input_gssapi_exchange_complete(int type, |
|
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, |
|
authctxt->pw)); |
|
|
|
+ if (authenticated) |
|
+ authctxt->last_details = ssh_gssapi_get_displayname(); |
|
+ |
|
authctxt->postponed = 0; |
|
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); |
|
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); |
|
@@ -322,6 +325,9 @@ input_gssapi_mic(int type, u_int32_t ple |
|
else |
|
logit("GSSAPI MIC check failed"); |
|
|
|
+ if (authenticated) |
|
+ authctxt->last_details = ssh_gssapi_get_displayname(); |
|
+ |
|
buffer_free(&b); |
|
if (micuser != authctxt->user) |
|
free(micuser); |
|
diff -up openssh-7.4p1/auth2-hostbased.c.expose-pam openssh-7.4p1/auth2-hostbased.c |
|
--- openssh-7.4p1/auth2-hostbased.c.expose-pam 2016-12-23 15:40:26.731447862 +0100 |
|
+++ openssh-7.4p1/auth2-hostbased.c 2016-12-23 15:40:26.818447876 +0100 |
|
@@ -60,7 +60,7 @@ userauth_hostbased(Authctxt *authctxt) |
|
{ |
|
Buffer b; |
|
Key *key = NULL; |
|
- char *pkalg, *cuser, *chost, *service; |
|
+ char *pkalg, *cuser, *chost, *service, *pubkey; |
|
u_char *pkblob, *sig; |
|
u_int alen, blen, slen; |
|
int pktype; |
|
@@ -140,15 +140,21 @@ userauth_hostbased(Authctxt *authctxt) |
|
buffer_dump(&b); |
|
#endif |
|
|
|
- pubkey_auth_info(authctxt, key, |
|
- "client user \"%.100s\", client host \"%.100s\"", cuser, chost); |
|
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash); |
|
+ auth_info(authctxt, |
|
+ "%s, client user \"%.100s\", client host \"%.100s\"", |
|
+ pubkey, cuser, chost); |
|
|
|
/* test for allowed key and correct signature */ |
|
authenticated = 0; |
|
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && |
|
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), |
|
- buffer_len(&b))) == 1) |
|
+ buffer_len(&b))) == 1) { |
|
authenticated = 1; |
|
+ authctxt->last_details = pubkey; |
|
+ } else { |
|
+ free(pubkey); |
|
+ } |
|
|
|
buffer_free(&b); |
|
done: |
|
diff -up openssh-7.4p1/auth2-pubkey.c.expose-pam openssh-7.4p1/auth2-pubkey.c |
|
--- openssh-7.4p1/auth2-pubkey.c.expose-pam 2016-12-23 15:40:26.746447864 +0100 |
|
+++ openssh-7.4p1/auth2-pubkey.c 2016-12-23 15:40:26.819447876 +0100 |
|
@@ -79,7 +79,7 @@ userauth_pubkey(Authctxt *authctxt) |
|
{ |
|
Buffer b; |
|
Key *key = NULL; |
|
- char *pkalg, *userstyle, *fp = NULL; |
|
+ char *pkalg, *userstyle, *pubkey, *fp = NULL; |
|
u_char *pkblob, *sig; |
|
u_int alen, blen, slen; |
|
int have_sig, pktype; |
|
@@ -177,7 +177,8 @@ userauth_pubkey(Authctxt *authctxt) |
|
#ifdef DEBUG_PK |
|
buffer_dump(&b); |
|
#endif |
|
- pubkey_auth_info(authctxt, key, NULL); |
|
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash); |
|
+ auth_info(authctxt, "%s", pubkey); |
|
|
|
/* test for correct signature */ |
|
authenticated = 0; |
|
@@ -185,9 +186,12 @@ userauth_pubkey(Authctxt *authctxt) |
|
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), |
|
buffer_len(&b))) == 1) { |
|
authenticated = 1; |
|
+ authctxt->last_details = pubkey; |
|
/* Record the successful key to prevent reuse */ |
|
auth2_record_userkey(authctxt, key); |
|
key = NULL; /* Don't free below */ |
|
+ } else { |
|
+ free(pubkey); |
|
} |
|
buffer_free(&b); |
|
free(sig); |
|
@@ -228,7 +232,7 @@ done: |
|
void |
|
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) |
|
{ |
|
- char *fp, *extra; |
|
+ char *extra, *pubkey; |
|
va_list ap; |
|
int i; |
|
|
|
@@ -238,27 +242,13 @@ pubkey_auth_info(Authctxt *authctxt, con |
|
i = vasprintf(&extra, fmt, ap); |
|
va_end(ap); |
|
if (i < 0 || extra == NULL) |
|
- fatal("%s: vasprintf failed", __func__); |
|
+ fatal("%s: vasprintf failed", __func__); |
|
} |
|
|
|
- if (key_is_cert(key)) { |
|
- fp = sshkey_fingerprint(key->cert->signature_key, |
|
- options.fingerprint_hash, SSH_FP_DEFAULT); |
|
- auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", |
|
- key_type(key), key->cert->key_id, |
|
- (unsigned long long)key->cert->serial, |
|
- key_type(key->cert->signature_key), |
|
- fp == NULL ? "(null)" : fp, |
|
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra); |
|
- free(fp); |
|
- } else { |
|
- fp = sshkey_fingerprint(key, options.fingerprint_hash, |
|
- SSH_FP_DEFAULT); |
|
- auth_info(authctxt, "%s %s%s%s", key_type(key), |
|
- fp == NULL ? "(null)" : fp, |
|
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra); |
|
- free(fp); |
|
- } |
|
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash); |
|
+ auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ", |
|
+ extra == NULL ? "" : extra); |
|
+ free(pubkey); |
|
free(extra); |
|
} |
|
|
|
diff -up openssh-7.4p1/auth.h.expose-pam openssh-7.4p1/auth.h |
|
--- openssh-7.4p1/auth.h.expose-pam 2016-12-23 15:40:26.782447870 +0100 |
|
+++ openssh-7.4p1/auth.h 2016-12-23 15:40:26.819447876 +0100 |
|
@@ -84,6 +84,9 @@ struct Authctxt { |
|
|
|
struct sshkey **prev_userkeys; |
|
u_int nprev_userkeys; |
|
+ |
|
+ char *last_details; |
|
+ char *auth_details; |
|
}; |
|
/* |
|
* Every authentication method has to handle authentication requests for |
|
diff -up openssh-7.4p1/auth-pam.c.expose-pam openssh-7.4p1/auth-pam.c |
|
--- openssh-7.4p1/auth-pam.c.expose-pam 2016-12-23 15:40:26.731447862 +0100 |
|
+++ openssh-7.4p1/auth-pam.c 2016-12-23 15:40:26.819447876 +0100 |
|
@@ -688,6 +688,11 @@ sshpam_init_ctx(Authctxt *authctxt) |
|
return (NULL); |
|
} |
|
|
|
+ /* Notify PAM about any already successful auth methods */ |
|
+ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMONLY && |
|
+ authctxt->auth_details) |
|
+ do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details); |
|
+ |
|
ctxt = xcalloc(1, sizeof *ctxt); |
|
|
|
/* Start the authentication thread */ |
|
diff -up openssh-7.4p1/gss-serv.c.expose-pam openssh-7.4p1/gss-serv.c |
|
--- openssh-7.4p1/gss-serv.c.expose-pam 2016-12-23 15:40:26.808447874 +0100 |
|
+++ openssh-7.4p1/gss-serv.c 2016-12-23 15:40:26.819447876 +0100 |
|
@@ -441,6 +441,16 @@ ssh_gssapi_do_child(char ***envp, u_int |
|
} |
|
|
|
/* Privileged */ |
|
+char* |
|
+ssh_gssapi_get_displayname(void) |
|
+{ |
|
+ if (gssapi_client.displayname.length != 0 && |
|
+ gssapi_client.displayname.value != NULL) |
|
+ return strdup((char *)gssapi_client.displayname.value); |
|
+ return NULL; |
|
+} |
|
+ |
|
+/* Privileged */ |
|
int |
|
ssh_gssapi_userok(char *user, struct passwd *pw) |
|
{ |
|
diff -up openssh-7.4p1/monitor.c.expose-pam openssh-7.4p1/monitor.c |
|
--- openssh-7.4p1/monitor.c.expose-pam 2016-12-23 15:40:26.794447872 +0100 |
|
+++ openssh-7.4p1/monitor.c 2016-12-23 15:41:16.473455863 +0100 |
|
@@ -300,6 +300,7 @@ monitor_child_preauth(Authctxt *_authctx |
|
{ |
|
struct mon_table *ent; |
|
int authenticated = 0, partial = 0; |
|
+ char *prev_auth_details; |
|
|
|
debug3("preauth child monitor started"); |
|
|
|
@@ -330,6 +331,18 @@ monitor_child_preauth(Authctxt *_authctx |
|
auth_submethod = NULL; |
|
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); |
|
|
|
+ if (authenticated) { |
|
+ prev_auth_details = authctxt->auth_details; |
|
+ xasprintf(&authctxt->auth_details, "%s%s%s%s%s", |
|
+ prev_auth_details ? prev_auth_details : "", |
|
+ prev_auth_details ? ", " : "", auth_method, |
|
+ authctxt->last_details ? ": " : "", |
|
+ authctxt->last_details ? authctxt->last_details : ""); |
|
+ free(prev_auth_details); |
|
+ } |
|
+ free(authctxt->last_details); |
|
+ authctxt->last_details = NULL; |
|
+ |
|
/* Special handling for multiple required authentications */ |
|
if (options.num_auth_methods != 0) { |
|
if (authenticated && |
|
@@ -1417,6 +1430,10 @@ mm_answer_keyverify(int sock, Buffer *m) |
|
debug3("%s: key %p signature %s", |
|
__func__, key, (verified == 1) ? "verified" : "unverified"); |
|
|
|
+ if (verified == 1) |
|
+ authctxt->last_details = sshkey_format_oneline(key, |
|
+ options.fingerprint_hash); |
|
+ |
|
/* If auth was successful then record key to ensure it isn't reused */ |
|
if (verified == 1 && key_blobtype == MM_USERKEY) |
|
auth2_record_userkey(authctxt, key); |
|
@@ -1860,6 +1877,9 @@ mm_answer_gss_userok(int sock, Buffer *m |
|
|
|
auth_method = "gssapi-with-mic"; |
|
|
|
+ if (authenticated) |
|
+ authctxt->last_details = ssh_gssapi_get_displayname(); |
|
+ |
|
/* Monitor loop will terminate if authenticated */ |
|
return (authenticated); |
|
} |
|
diff -up openssh-7.4p1/servconf.c.expose-pam openssh-7.4p1/servconf.c |
|
--- openssh-7.4p1/servconf.c.expose-pam 2016-12-23 15:40:26.810447875 +0100 |
|
+++ openssh-7.4p1/servconf.c 2016-12-23 15:44:04.691482920 +0100 |
|
@@ -171,6 +171,7 @@ initialize_server_options(ServerOptions |
|
options->version_addendum = NULL; |
|
options->use_kuserok = -1; |
|
options->enable_k5users = -1; |
|
+ options->expose_auth_methods = -1; |
|
options->fingerprint_hash = -1; |
|
options->disable_forwarding = -1; |
|
} |
|
@@ -354,6 +355,8 @@ fill_default_server_options(ServerOption |
|
options->use_kuserok = 1; |
|
if (options->enable_k5users == -1) |
|
options->enable_k5users = 0; |
|
+ if (options->expose_auth_methods == -1) |
|
+ options->expose_auth_methods = EXPOSE_AUTHMETH_NEVER; |
|
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) |
|
options->fwd_opts.streamlocal_bind_mask = 0177; |
|
if (options->fwd_opts.streamlocal_bind_unlink == -1) |
|
@@ -439,6 +442,7 @@ typedef enum { |
|
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, |
|
sStreamLocalBindMask, sStreamLocalBindUnlink, |
|
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, |
|
+ sExposeAuthenticationMethods, |
|
sDeprecated, sIgnore, sUnsupported |
|
} ServerOpCodes; |
|
|
|
@@ -595,6 +599,7 @@ static struct { |
|
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, |
|
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, |
|
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL }, |
|
+ { "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_ALL }, |
|
{ NULL, sBadOption, 0 } |
|
}; |
|
|
|
@@ -984,6 +989,12 @@ static const struct multistate multistat |
|
{ "local", FORWARD_LOCAL }, |
|
{ NULL, -1 } |
|
}; |
|
+static const struct multistate multistate_exposeauthmeth[] = { |
|
+ { "never", EXPOSE_AUTHMETH_NEVER }, |
|
+ { "pam-only", EXPOSE_AUTHMETH_PAMONLY }, |
|
+ { "pam-and-env", EXPOSE_AUTHMETH_PAMENV }, |
|
+ { NULL, -1} |
|
+}; |
|
|
|
int |
|
process_server_config_line(ServerOptions *options, char *line, |
|
@@ -1902,6 +1913,11 @@ process_server_config_line(ServerOptions |
|
options->fingerprint_hash = value; |
|
break; |
|
|
|
+ case sExposeAuthenticationMethods: |
|
+ intptr = &options->expose_auth_methods; |
|
+ multistate_ptr = multistate_exposeauthmeth; |
|
+ goto parse_multistate; |
|
+ |
|
case sDeprecated: |
|
case sIgnore: |
|
case sUnsupported: |
|
@@ -2060,6 +2076,7 @@ copy_set_server_options(ServerOptions *d |
|
M_CP_INTOPT(enable_k5users); |
|
M_CP_INTOPT(rekey_limit); |
|
M_CP_INTOPT(rekey_interval); |
|
+ M_CP_INTOPT(expose_auth_methods); |
|
|
|
/* |
|
* The bind_mask is a mode_t that may be unsigned, so we can't use |
|
@@ -2176,6 +2193,8 @@ fmt_intarg(ServerOpCodes code, int val) |
|
return fmt_multistate_int(val, multistate_tcpfwd); |
|
case sFingerprintHash: |
|
return ssh_digest_alg_name(val); |
|
+ case sExposeAuthenticationMethods: |
|
+ return fmt_multistate_int(val, multistate_exposeauthmeth); |
|
default: |
|
switch (val) { |
|
case 0: |
|
@@ -2356,6 +2375,7 @@ dump_config(ServerOptions *o) |
|
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); |
|
dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); |
|
dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users); |
|
+ dump_cfg_fmtint(sExposeAuthenticationMethods, o->expose_auth_methods); |
|
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); |
|
|
|
/* string arguments */ |
|
diff -up openssh-7.4p1/servconf.h.expose-pam openssh-7.4p1/servconf.h |
|
--- openssh-7.4p1/servconf.h.expose-pam 2016-12-23 15:40:26.810447875 +0100 |
|
+++ openssh-7.4p1/servconf.h 2016-12-23 15:40:26.821447876 +0100 |
|
@@ -48,6 +48,11 @@ |
|
#define FORWARD_LOCAL (1<<1) |
|
#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) |
|
|
|
+/* Expose AuthenticationMethods */ |
|
+#define EXPOSE_AUTHMETH_NEVER 0 |
|
+#define EXPOSE_AUTHMETH_PAMONLY 1 |
|
+#define EXPOSE_AUTHMETH_PAMENV 2 |
|
+ |
|
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ |
|
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ |
|
|
|
@@ -195,6 +200,8 @@ typedef struct { |
|
char *auth_methods[MAX_AUTH_METHODS]; |
|
|
|
int fingerprint_hash; |
|
+ |
|
+ int expose_auth_methods; /* EXPOSE_AUTHMETH_* above */ |
|
} ServerOptions; |
|
|
|
/* Information about the incoming connection as used by Match */ |
|
diff -up openssh-7.4p1/session.c.expose-pam openssh-7.4p1/session.c |
|
--- openssh-7.4p1/session.c.expose-pam 2016-12-23 15:40:26.794447872 +0100 |
|
+++ openssh-7.4p1/session.c 2016-12-23 15:40:26.821447876 +0100 |
|
@@ -997,6 +997,12 @@ copy_environment(char **source, char *** |
|
} |
|
*var_val++ = '\0'; |
|
|
|
+ if (options.expose_auth_methods < EXPOSE_AUTHMETH_PAMENV && |
|
+ strcmp(var_name, "SSH_USER_AUTH") == 0) { |
|
+ free(var_name); |
|
+ continue; |
|
+ } |
|
+ |
|
debug3("Copy environment: %s=%s", var_name, var_val); |
|
child_set_env(env, envsize, var_name, var_val); |
|
|
|
@@ -1173,6 +1179,11 @@ do_setup_env(Session *s, const char *she |
|
} |
|
#endif /* USE_PAM */ |
|
|
|
+ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMENV && |
|
+ s->authctxt->auth_details) |
|
+ child_set_env(&env, &envsize, "SSH_USER_AUTH", |
|
+ s->authctxt->auth_details); |
|
+ |
|
if (auth_sock_name != NULL) |
|
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, |
|
auth_sock_name); |
|
@@ -2561,6 +2572,9 @@ do_cleanup(Authctxt *authctxt) |
|
if (authctxt == NULL) |
|
return; |
|
|
|
+ free(authctxt->auth_details); |
|
+ authctxt->auth_details = NULL; |
|
+ |
|
#ifdef USE_PAM |
|
if (options.use_pam) { |
|
sshpam_cleanup(); |
|
diff -up openssh-7.4p1/ssh.1.expose-pam openssh-7.4p1/ssh.1 |
|
--- openssh-7.4p1/ssh.1.expose-pam 2016-12-23 15:40:26.810447875 +0100 |
|
+++ openssh-7.4p1/ssh.1 2016-12-23 15:40:26.822447877 +0100 |
|
@@ -1421,6 +1421,10 @@ server IP address, and server port numbe |
|
This variable contains the original command line if a forced command |
|
is executed. |
|
It can be used to extract the original arguments. |
|
+.It Ev SSH_USER_AUTH |
|
+This variable contains, for SSH2 only, a comma-separated list of authentication |
|
+methods that were successfuly used to authenticate. When possible, these |
|
+methods are extended with detailed information on the credential used. |
|
.It Ev SSH_TTY |
|
This is set to the name of the tty (path to the device) associated |
|
with the current shell or command. |
|
diff -up openssh-7.4p1/sshd_config.5.expose-pam openssh-7.4p1/sshd_config.5 |
|
--- openssh-7.4p1/sshd_config.5.expose-pam 2016-12-23 15:40:26.822447877 +0100 |
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:45:22.411495421 +0100 |
|
@@ -570,6 +570,21 @@ Disables all forwarding features, includ |
|
TCP and StreamLocal. |
|
This option overrides all other forwarding-related options and may |
|
simplify restricted configurations. |
|
+.It Cm ExposeAuthenticationMethods |
|
+When using SSH2, this option controls the exposure of the list of |
|
+successful authentication methods to PAM during the authentication |
|
+and to the shell environment via the |
|
+.Cm SSH_USER_AUTH |
|
+variable. See the description of this variable for more details. |
|
+Valid options are: |
|
+.Cm never |
|
+(Do not expose successful authentication methods), |
|
+.Cm pam-only |
|
+(Only expose them to PAM during authentication, not afterwards), |
|
+.Cm pam-and-env |
|
+(Expose them to PAM and keep them in the shell environment). |
|
+The default is |
|
+.Cm never . |
|
.It Cm FingerprintHash |
|
Specifies the hash algorithm used when logging key fingerprints. |
|
Valid options are: |
|
diff -up openssh-7.4p1/ssh-gss.h.expose-pam openssh-7.4p1/ssh-gss.h |
|
--- openssh-7.4p1/ssh-gss.h.expose-pam 2016-12-23 15:40:26.811447875 +0100 |
|
+++ openssh-7.4p1/ssh-gss.h 2016-12-23 15:40:26.823447877 +0100 |
|
@@ -159,6 +159,7 @@ int ssh_gssapi_server_check_mech(Gssctxt |
|
const char *); |
|
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); |
|
int ssh_gssapi_userok(char *name, struct passwd *); |
|
+char* ssh_gssapi_get_displayname(void); |
|
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); |
|
void ssh_gssapi_do_child(char ***, u_int *); |
|
void ssh_gssapi_cleanup_creds(void); |
|
diff -up openssh-7.4p1/sshkey.c.expose-pam openssh-7.4p1/sshkey.c |
|
--- openssh-7.4p1/sshkey.c.expose-pam 2016-12-23 15:40:26.777447869 +0100 |
|
+++ openssh-7.4p1/sshkey.c 2016-12-23 15:40:26.823447877 +0100 |
|
@@ -57,6 +57,7 @@ |
|
#define SSHKEY_INTERNAL |
|
#include "sshkey.h" |
|
#include "match.h" |
|
+#include "xmalloc.h" |
|
|
|
/* openssh private key file format */ |
|
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" |
|
@@ -1191,6 +1192,30 @@ sshkey_fingerprint(const struct sshkey * |
|
return retval; |
|
} |
|
|
|
+char * |
|
+sshkey_format_oneline(const struct sshkey *key, int dgst_alg) |
|
+{ |
|
+ char *fp, *result; |
|
+ |
|
+ if (sshkey_is_cert(key)) { |
|
+ fp = sshkey_fingerprint(key->cert->signature_key, dgst_alg, |
|
+ SSH_FP_DEFAULT); |
|
+ xasprintf(&result, "%s ID %s (serial %llu) CA %s %s", |
|
+ sshkey_type(key), key->cert->key_id, |
|
+ (unsigned long long)key->cert->serial, |
|
+ sshkey_type(key->cert->signature_key), |
|
+ fp == NULL ? "(null)" : fp); |
|
+ free(fp); |
|
+ } else { |
|
+ fp = sshkey_fingerprint(key, dgst_alg, SSH_FP_DEFAULT); |
|
+ xasprintf(&result, "%s %s", sshkey_type(key), |
|
+ fp == NULL ? "(null)" : fp); |
|
+ free(fp); |
|
+ } |
|
+ |
|
+ return result; |
|
+} |
|
+ |
|
#ifdef WITH_SSH1 |
|
/* |
|
* Reads a multiple-precision integer in decimal from the buffer, and advances |
|
diff -up openssh-7.4p1/sshkey.h.expose-pam openssh-7.4p1/sshkey.h |
|
--- openssh-7.4p1/sshkey.h.expose-pam 2016-12-23 15:40:26.777447869 +0100 |
|
+++ openssh-7.4p1/sshkey.h 2016-12-23 15:40:26.823447877 +0100 |
|
@@ -124,6 +124,7 @@ char *sshkey_fingerprint(const struct s |
|
int, enum sshkey_fp_rep); |
|
int sshkey_fingerprint_raw(const struct sshkey *k, |
|
int, u_char **retp, size_t *lenp); |
|
+char *sshkey_format_oneline(const struct sshkey *k, int dgst_alg); |
|
const char *sshkey_type(const struct sshkey *); |
|
const char *sshkey_cert_type(const struct sshkey *); |
|
int sshkey_write(const struct sshkey *, FILE *);
|
|
|