Ticket #27250: openssh-5.3p1-gsskex-all-20100124.patch

File openssh-5.3p1-gsskex-all-20100124.patch, 88.2 KB (added by lassi.tuura@…, 13 years ago)

Actual patch

  • openssh-5.3p1

    old new  
    11/* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    4545#include "channels.h"
    4646#include "session.h"
    4747#include "misc.h"
     48#include "servconf.h"
     49#include "uidswap.h"
    4850
    4951#include "ssh-gss.h"
     52#include "monitor_wrap.h"
     53
     54extern ServerOptions options;
    5055
    5156static ssh_gssapi_client gssapi_client =
    5257    { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
    53     GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
     58    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
    5459
    5560ssh_gssapi_mech gssapi_null_mech =
    56     { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
     61    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
    5762
    5863#ifdef KRB5
    5964extern ssh_gssapi_mech gssapi_kerberos_mech;
     
    8186        char lname[MAXHOSTNAMELEN];
    8287        gss_OID_set oidset;
    8388
    84         gss_create_empty_oid_set(&status, &oidset);
    85         gss_add_oid_set_member(&status, ctx->oid, &oidset);
     89        if (options.gss_strict_acceptor) {
     90                gss_create_empty_oid_set(&status, &oidset);
     91                gss_add_oid_set_member(&status, ctx->oid, &oidset);
     92
     93                if (gethostname(lname, MAXHOSTNAMELEN)) {
     94                        gss_release_oid_set(&status, &oidset);
     95                        return (-1);
     96                }
    8697
    87         if (gethostname(lname, MAXHOSTNAMELEN)) {
    88                 gss_release_oid_set(&status, &oidset);
    89                 return (-1);
    90         }
     98                if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
     99                        gss_release_oid_set(&status, &oidset);
     100                        return (ctx->major);
     101                }
     102
     103                if ((ctx->major = gss_acquire_cred(&ctx->minor,
     104                    ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds,
     105                    NULL, NULL)))
     106                        ssh_gssapi_error(ctx);
    91107
    92         if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
    93108                gss_release_oid_set(&status, &oidset);
    94109                return (ctx->major);
     110        } else {
     111                ctx->name = GSS_C_NO_NAME;
     112                ctx->creds = GSS_C_NO_CREDENTIAL;
    95113        }
    96 
    97         if ((ctx->major = gss_acquire_cred(&ctx->minor,
    98             ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL)))
    99                 ssh_gssapi_error(ctx);
    100 
    101         gss_release_oid_set(&status, &oidset);
    102         return (ctx->major);
     114        return GSS_S_COMPLETE;
    103115}
    104116
    105117/* Privileged */
     
    114126}
    115127
    116128/* Unprivileged */
     129char *
     130ssh_gssapi_server_mechanisms() {
     131        gss_OID_set     supported;
     132
     133        ssh_gssapi_supported_oids(&supported);
     134        return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
     135            NULL, NULL));
     136}
     137
     138/* Unprivileged */
     139int
     140ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
     141    const char *dummy) {
     142        Gssctxt *ctx = NULL;
     143        int res;
     144 
     145        res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
     146        ssh_gssapi_delete_ctx(&ctx);
     147
     148        return (res);
     149}
     150
     151/* Unprivileged */
    117152void
    118153ssh_gssapi_supported_oids(gss_OID_set *oidset)
    119154{
     
    123158        gss_OID_set supported;
    124159
    125160        gss_create_empty_oid_set(&min_status, oidset);
    126         gss_indicate_mechs(&min_status, &supported);
     161
     162        if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported)))
     163                return;
    127164
    128165        while (supported_mechs[i]->name != NULL) {
    129166                if (GSS_ERROR(gss_test_oid_set_member(&min_status,
     
    247284ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
    248285{
    249286        int i = 0;
     287        int equal = 0;
     288        gss_name_t new_name = GSS_C_NO_NAME;
     289        gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
     290
     291        if (options.gss_store_rekey && client->used && ctx->client_creds) {
     292                if (client->mech->oid.length != ctx->oid->length ||
     293                    (memcmp(client->mech->oid.elements,
     294                     ctx->oid->elements, ctx->oid->length) !=0)) {
     295                        debug("Rekeyed credentials have different mechanism");
     296                        return GSS_S_COMPLETE;
     297                }
     298
     299                if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
     300                    ctx->client_creds, ctx->oid, &new_name,
     301                    NULL, NULL, NULL))) {
     302                        ssh_gssapi_error(ctx);
     303                        return (ctx->major);
     304                }
     305
     306                ctx->major = gss_compare_name(&ctx->minor, client->name,
     307                    new_name, &equal);
    250308
    251         gss_buffer_desc ename;
     309                if (GSS_ERROR(ctx->major)) {
     310                        ssh_gssapi_error(ctx);
     311                        return (ctx->major);
     312                }
     313 
     314                if (!equal) {
     315                        debug("Rekeyed credentials have different name");
     316                        return GSS_S_COMPLETE;
     317                }
     318
     319                debug("Marking rekeyed credentials for export");
     320
     321                gss_release_name(&ctx->minor, &client->name);
     322                gss_release_cred(&ctx->minor, &client->creds);
     323                client->name = new_name;
     324                client->creds = ctx->client_creds;
     325                ctx->client_creds = GSS_C_NO_CREDENTIAL;
     326                client->updated = 1;
     327                return GSS_S_COMPLETE;
     328        }
    252329
    253330        client->mech = NULL;
    254331
     
    263340        if (client->mech == NULL)
    264341                return GSS_S_FAILURE;
    265342
     343        if (ctx->client_creds &&
     344            (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
     345             ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
     346                ssh_gssapi_error(ctx);
     347                return (ctx->major);
     348        }
     349
    266350        if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
    267351            &client->displayname, NULL))) {
    268352                ssh_gssapi_error(ctx);
     
    280364                return (ctx->major);
    281365        }
    282366
     367        gss_release_buffer(&ctx->minor, &ename);
     368
    283369        /* We can't copy this structure, so we just move the pointer to it */
    284370        client->creds = ctx->client_creds;
    285371        ctx->client_creds = GSS_C_NO_CREDENTIAL;
     
    327413
    328414/* Privileged */
    329415int
    330 ssh_gssapi_userok(char *user)
     416ssh_gssapi_userok(char *user, struct passwd *pw)
    331417{
    332418        OM_uint32 lmin;
    333419
     
    337423                return 0;
    338424        }
    339425        if (gssapi_client.mech && gssapi_client.mech->userok)
    340                 if ((*gssapi_client.mech->userok)(&gssapi_client, user))
     426                if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
     427                        gssapi_client.used = 1;
     428                        gssapi_client.store.owner = pw;
    341429                        return 1;
    342                 else {
     430                } else {
    343431                        /* Destroy delegated credentials if userok fails */
    344432                        gss_release_buffer(&lmin, &gssapi_client.displayname);
    345433                        gss_release_buffer(&lmin, &gssapi_client.exportedname);
     
    352440        return (0);
    353441}
    354442
    355 /* Privileged */
    356 OM_uint32
    357 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
     443/* These bits are only used for rekeying. The unpriviledged child is running
     444 * as the user, the monitor is root.
     445 *
     446 * In the child, we want to :
     447 *    *) Ask the monitor to store our credentials into the store we specify
     448 *    *) If it succeeds, maybe do a PAM update
     449 */
     450
     451/* Stuff for PAM */
     452
     453#ifdef USE_PAM
     454static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg,
     455    struct pam_response **resp, void *data)
    358456{
    359         ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
    360             gssbuf, gssmic, NULL);
     457        return (PAM_CONV_ERR);
     458}
     459#endif
    361460
    362         return (ctx->major);
     461void
     462ssh_gssapi_rekey_creds() {
     463        int ok;
     464        int ret;
     465#ifdef USE_PAM
     466        pam_handle_t *pamh = NULL;
     467        struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
     468        char *envstr;
     469#endif
     470
     471        if (gssapi_client.store.filename == NULL &&
     472            gssapi_client.store.envval == NULL &&
     473            gssapi_client.store.envvar == NULL)
     474                return;
     475 
     476        ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
     477
     478        if (!ok)
     479                return;
     480
     481        debug("Rekeyed credentials stored successfully");
     482
     483        /* Actually managing to play with the ssh pam stack from here will
     484         * be next to impossible. In any case, we may want different options
     485         * for rekeying. So, use our own :)
     486         */
     487#ifdef USE_PAM 
     488        if (!use_privsep) {
     489                debug("Not even going to try and do PAM with privsep disabled");
     490                return;
     491        }
     492
     493        ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
     494            &pamconv, &pamh);
     495        if (ret)
     496                return;
     497
     498        xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar,
     499            gssapi_client.store.envval);
     500
     501        ret = pam_putenv(pamh, envstr);
     502        if (!ret)
     503                pam_setcred(pamh, PAM_REINITIALIZE_CRED);
     504        pam_end(pamh, PAM_SUCCESS);
     505#endif
     506}
     507
     508int
     509ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
     510        int ok = 0;
     511
     512        /* Check we've got credentials to store */
     513        if (!gssapi_client.updated)
     514                return 0;
     515
     516        gssapi_client.updated = 0;
     517
     518        temporarily_use_uid(gssapi_client.store.owner);
     519        if (gssapi_client.mech && gssapi_client.mech->updatecreds)
     520                ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
     521        else
     522                debug("No update function for this mechanism");
     523
     524        restore_uid();
     525
     526        return ok;
    363527}
    364528
    365529#endif
  • openssh-5.3p1

    old new  
    9292        options->kerberos_ticket_cleanup = -1;
    9393        options->kerberos_get_afs_token = -1;
    9494        options->gss_authentication=-1;
     95        options->gss_keyex = -1;
    9596        options->gss_cleanup_creds = -1;
     97        options->gss_strict_acceptor = -1;
     98        options->gss_store_rekey = -1;
    9699        options->password_authentication = -1;
    97100        options->kbd_interactive_authentication = -1;
    98101        options->challenge_response_authentication = -1;
     
    210213                options->kerberos_get_afs_token = 0;
    211214        if (options->gss_authentication == -1)
    212215                options->gss_authentication = 0;
     216        if (options->gss_keyex == -1)
     217                options->gss_keyex = 0;
    213218        if (options->gss_cleanup_creds == -1)
    214219                options->gss_cleanup_creds = 1;
     220        if (options->gss_strict_acceptor == -1)
     221                options->gss_strict_acceptor = 1;
     222        if (options->gss_store_rekey == -1)
     223                options->gss_store_rekey = 0;
    215224        if (options->password_authentication == -1)
    216225                options->password_authentication = 1;
    217226        if (options->kbd_interactive_authentication == -1)
     
    302311        sBanner, sUseDNS, sHostbasedAuthentication,
    303312        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
    304313        sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
    305         sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
     314        sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
     315        sGssKeyEx, sGssStoreRekey,
     316        sAcceptEnv, sPermitTunnel,
    306317        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
    307318        sUsePrivilegeSeparation, sAllowAgentForwarding,
    308319        sZeroKnowledgePasswordAuthentication,
     
    364375#ifdef GSSAPI
    365376        { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
    366377        { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
     378        { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
     379        { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
     380        { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
    367381#else
    368382        { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
    369383        { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
     384        { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
     385        { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
     386        { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
    370387#endif
    371388        { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
    372389        { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
     
    891908                intptr = &options->gss_authentication;
    892909                goto parse_flag;
    893910
     911        case sGssKeyEx:
     912                intptr = &options->gss_keyex;
     913                goto parse_flag;
     914
    894915        case sGssCleanupCreds:
    895916                intptr = &options->gss_cleanup_creds;
    896917                goto parse_flag;
    897918
     919        case sGssStrictAcceptor:
     920                intptr = &options->gss_strict_acceptor;
     921                goto parse_flag;
     922
     923        case sGssStoreRekey:
     924                intptr = &options->gss_store_rekey;
     925                goto parse_flag;
     926
    898927        case sPasswordAuthentication:
    899928                intptr = &options->password_authentication;
    900929                goto parse_flag;
  • openssh-5.3p1

    old new  
    9191        int     kerberos_get_afs_token;         /* If true, try to get AFS token if
    9292                                                 * authenticated with Kerberos. */
    9393        int     gss_authentication;     /* If true, permit GSSAPI authentication */
     94        int     gss_keyex;              /* If true, permit GSSAPI key exchange */
    9495        int     gss_cleanup_creds;      /* If true, destroy cred cache on logout */
     96        int     gss_strict_acceptor;    /* If true, restrict the GSSAPI acceptor name */
     97        int     gss_store_rekey;
    9598        int     password_authentication;        /* If true, permit password
    9699                                                 * authentication. */
    97100        int     kbd_interactive_authentication; /* If true, permit */
  • openssh-5.3p1

    old new  
    7373# GSSAPI options
    7474#GSSAPIAuthentication no
    7575#GSSAPICleanupCredentials yes
     76#GSSAPIStrictAcceptorCheck yes
     77#GSSAPIKeyExchange no
    7678
    7779# Set this to 'yes' to enable PAM authentication, account processing,
    7880# and session processing. If this is enabled, PAM authentication will
  • sshd_config.5

    old new  
    379379The default is
    380380.Dq no .
    381381Note that this option applies to protocol version 2 only.
     382.It Cm GSSAPIKeyExchange
     383Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
     384doesn't rely on ssh keys to verify host identity.
     385The default is
     386.Dq no .
     387Note that this option applies to protocol version 2 only.
    382388.It Cm GSSAPICleanupCredentials
    383389Specifies whether to automatically destroy the user's credentials cache
    384390on logout.
    385391The default is
    386392.Dq yes .
    387393Note that this option applies to protocol version 2 only.
     394.It Cm GSSAPIStrictAcceptorCheck
     395Determines whether to be strict about the identity of the GSSAPI acceptor
     396a client authenticates against. If
     397.Dq yes
     398then the client must authenticate against the
     399.Pa host
     400service on the current hostname. If
     401.Dq no
     402then the client may authenticate against any service key stored in the
     403machine's default store. This facility is provided to assist with operation
     404on multi homed machines.
     405The default is
     406.Dq yes .
     407Note that this option applies only to protocol version 2 GSSAPI connections,
     408and setting it to
     409.Dq no
     410may only work with recent Kerberos GSSAPI libraries.
     411.It Cm GSSAPIStoreCredentialsOnRekey
     412Controls whether the user's GSSAPI credentials should be updated following a
     413successful connection rekeying. This option can be used to accepted renewed
     414or updated credentials from a compatible client. The default is
     415.Dq no .
    388416.It Cm HostbasedAuthentication
    389417Specifies whether rhosts or /etc/hosts.equiv authentication together
    390418with successful public key client host authentication is allowed
  • openssh-5.3p1

    old new  
    127127        oClearAllForwardings, oNoHostAuthenticationForLocalhost,
    128128        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
    129129        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
     130        oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
    130131        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
    131132        oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
    132133        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
     
    164165        { "afstokenpassing", oUnsupported },
    165166#if defined(GSSAPI)
    166167        { "gssapiauthentication", oGssAuthentication },
     168        { "gssapikeyexchange", oGssKeyEx },
    167169        { "gssapidelegatecredentials", oGssDelegateCreds },
     170        { "gssapitrustdns", oGssTrustDns },
     171        { "gssapiclientidentity", oGssClientIdentity },
     172        { "gssapirenewalforcesrekey", oGssRenewalRekey },
    168173#else
    169174        { "gssapiauthentication", oUnsupported },
     175        { "gssapikeyexchange", oUnsupported },
    170176        { "gssapidelegatecredentials", oUnsupported },
     177        { "gssapitrustdns", oUnsupported },
     178        { "gssapiclientidentity", oUnsupported },
     179        { "gssapirenewalforcesrekey", oUnsupported },
    171180#endif
    172181        { "fallbacktorsh", oDeprecated },
    173182        { "usersh", oDeprecated },
     
    454463                intptr = &options->gss_authentication;
    455464                goto parse_flag;
    456465
     466        case oGssKeyEx:
     467                intptr = &options->gss_keyex;
     468                goto parse_flag;
     469
    457470        case oGssDelegateCreds:
    458471                intptr = &options->gss_deleg_creds;
    459472                goto parse_flag;
    460473
     474        case oGssTrustDns:
     475                intptr = &options->gss_trust_dns;
     476                goto parse_flag;
     477
     478        case oGssClientIdentity:
     479                charptr = &options->gss_client_identity;
     480                goto parse_string;
     481
     482        case oGssRenewalRekey:
     483                intptr = &options->gss_renewal_rekey;
     484                goto parse_flag;
     485
    461486        case oBatchMode:
    462487                intptr = &options->batch_mode;
    463488                goto parse_flag;
     
    10131038        options->pubkey_authentication = -1;
    10141039        options->challenge_response_authentication = -1;
    10151040        options->gss_authentication = -1;
     1041        options->gss_keyex = -1;
    10161042        options->gss_deleg_creds = -1;
     1043        options->gss_trust_dns = -1;
     1044        options->gss_renewal_rekey = -1;
     1045        options->gss_client_identity = NULL;
    10171046        options->password_authentication = -1;
    10181047        options->kbd_interactive_authentication = -1;
    10191048        options->kbd_interactive_devices = NULL;
     
    11051134                options->challenge_response_authentication = 1;
    11061135        if (options->gss_authentication == -1)
    11071136                options->gss_authentication = 0;
     1137        if (options->gss_keyex == -1)
     1138                options->gss_keyex = 0;
    11081139        if (options->gss_deleg_creds == -1)
    11091140                options->gss_deleg_creds = 0;
     1141        if (options->gss_trust_dns == -1)
     1142                options->gss_trust_dns = 0;
     1143        if (options->gss_renewal_rekey == -1)
     1144                options->gss_renewal_rekey = 0;
    11101145        if (options->password_authentication == -1)
    11111146                options->password_authentication = 1;
    11121147        if (options->kbd_interactive_authentication == -1)
  • openssh-5.3p1

    old new  
    4444        int     challenge_response_authentication;
    4545                                        /* Try S/Key or TIS, authentication. */
    4646        int     gss_authentication;     /* Try GSS authentication */
     47        int     gss_keyex;              /* Try GSS key exchange */
    4748        int     gss_deleg_creds;        /* Delegate GSS credentials */
     49        int     gss_trust_dns;          /* Trust DNS for GSS canonicalization */
     50        int     gss_renewal_rekey;      /* Credential renewal forces rekey */
     51        char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
    4852        int     password_authentication;        /* Try password
    4953                                                 * authentication. */
    5054        int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
  • ssh_config.5

    old new  
    478478The default is
    479479.Dq no .
    480480Note that this option applies to protocol version 2 only.
     481.It Cm GSSAPIKeyExchange
     482Specifies whether key exchange based on GSSAPI may be used. When using
     483GSSAPI key exchange the server need not have a host key.
     484The default is
     485.Dq no .
     486Note that this option applies to protocol version 2 only.
     487.It Cm GSSAPIClientIdentity
     488If set, specifies the GSSAPI client identity that ssh should use when
     489connecting to the server. The default is unset, which means that the default
     490identity will be used.
    481491.It Cm GSSAPIDelegateCredentials
    482492Forward (delegate) credentials to the server.
    483493The default is
    484494.Dq no .
    485 Note that this option applies to protocol version 2 only.
     495Note that this option applies to protocol version 2 connections using GSSAPI.
     496.It Cm GSSAPIRenewalForcesRekey
     497If set to
     498.Dq yes
     499then renewal of the client's GSSAPI credentials will force the rekeying of the
     500ssh connection. With a compatible server, this can delegate the renewed
     501credentials to a session on the server.
     502The default is
     503.Dq no .
     504.It Cm GSSAPITrustDns
     505Set to
     506.Dq yes to indicate that the DNS is trusted to securely canonicalize
     507the name of the host being connected to. If
     508.Dq no, the hostname entered on the
     509command line will be passed untouched to the GSSAPI library.
     510The default is
     511.Dq no .
     512This option only applies to protocol version 2 connections using GSSAPI.
    486513.It Cm HashKnownHosts
    487514Indicates that
    488515.Xr ssh 1
  • sshconnect2.c

    old new  
    105105{
    106106        Kex *kex;
    107107
     108#ifdef GSSAPI
     109        char *orig = NULL, *gss = NULL;
     110        char *gss_host = NULL;
     111#endif
     112
    108113        xxx_host = host;
    109114        xxx_hostaddr = hostaddr;
    110115
     116#ifdef GSSAPI
     117        if (options.gss_keyex) {
     118                /* Add the GSSAPI mechanisms currently supported on this
     119                 * client to the key exchange algorithm proposal */
     120                orig = myproposal[PROPOSAL_KEX_ALGS];
     121
     122                if (options.gss_trust_dns)
     123                        gss_host = (char *)get_canonical_hostname(1);
     124                else
     125                        gss_host = host;
     126
     127                gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
     128                if (gss) {
     129                        debug("Offering GSSAPI proposal: %s", gss);
     130                        xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
     131                            "%s,%s", gss, orig);
     132                }
     133        }
     134#endif
     135
    111136        if (options.ciphers == (char *)-1) {
    112137                logit("No valid ciphers for protocol version 2 given, using defaults.");
    113138                options.ciphers = NULL;
     
    135160                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
    136161                    options.hostkeyalgorithms;
    137162
     163#ifdef GSSAPI
     164        /* If we've got GSSAPI algorithms, then we also support the
     165         * 'null' hostkey, as a last resort */
     166        if (options.gss_keyex && gss) {
     167                orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
     168                xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
     169                    "%s,null", orig);
     170                xfree(gss);
     171        }
     172#endif
     173
    138174        if (options.rekey_limit)
    139175                packet_set_rekey_limit((u_int32_t)options.rekey_limit);
    140176
     
    144180        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
    145181        kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
    146182        kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
     183#ifdef GSSAPI
     184        if (options.gss_keyex) {
     185                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
     186                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
     187                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
     188        }
     189#endif
    147190        kex->client_version_string=client_version_string;
    148191        kex->server_version_string=server_version_string;
    149192        kex->verify_host_key=&verify_host_key_callback;
    150193
     194#ifdef GSSAPI
     195        if (options.gss_keyex) {
     196                kex->gss_deleg_creds = options.gss_deleg_creds;
     197                kex->gss_trust_dns = options.gss_trust_dns;
     198                kex->gss_client = options.gss_client_identity;
     199                kex->gss_host = gss_host;
     200        }
     201#endif
     202
    151203        xxx_kex = kex;
    152204
    153205        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
     
    236288void    input_gssapi_hash(int type, u_int32_t, void *);
    237289void    input_gssapi_error(int, u_int32_t, void *);
    238290void    input_gssapi_errtok(int, u_int32_t, void *);
     291int     userauth_gsskeyex(Authctxt *authctxt);
    239292#endif
    240293
    241294void    userauth(Authctxt *, char *);
     
    251304
    252305Authmethod authmethods[] = {
    253306#ifdef GSSAPI
     307        {"gssapi-keyex",
     308                userauth_gsskeyex,
     309                NULL,
     310                &options.gss_authentication,
     311                NULL},
    254312        {"gssapi-with-mic",
    255313                userauth_gssapi,
    256314                NULL,
     
    542600        static u_int mech = 0;
    543601        OM_uint32 min;
    544602        int ok = 0;
     603        const char *gss_host;
     604
     605        if (options.gss_trust_dns)
     606                gss_host = get_canonical_hostname(1);
     607        else
     608                gss_host = authctxt->host;
    545609
    546610        /* Try one GSSAPI method at a time, rather than sending them all at
    547611         * once. */
    548612
    549613        if (gss_supported == NULL)
    550                 gss_indicate_mechs(&min, &gss_supported);
     614                if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
     615                        gss_supported = NULL;
     616                        return 0;
     617                }
    551618
    552619        /* Check to see if the mechanism is usable before we offer it */
    553620        while (mech < gss_supported->count && !ok) {
    554621                /* My DER encoding requires length<128 */
    555622                if (gss_supported->elements[mech].length < 128 &&
    556623                    ssh_gssapi_check_mechanism(&gssctxt,
    557                     &gss_supported->elements[mech], authctxt->host)) {
     624                    &gss_supported->elements[mech], gss_host,
     625                    options.gss_client_identity)) {
    558626                        ok = 1; /* Mechanism works */
    559627                } else {
    560628                        mech++;
     
    651719{
    652720        Authctxt *authctxt = ctxt;
    653721        Gssctxt *gssctxt;
    654         int oidlen;
    655         char *oidv;
     722        u_int oidlen;
     723        u_char *oidv;
    656724
    657725        if (authctxt == NULL)
    658726                fatal("input_gssapi_response: no authentication context");
     
    762830        xfree(msg);
    763831        xfree(lang);
    764832}
     833
     834int
     835userauth_gsskeyex(Authctxt *authctxt)
     836{
     837        Buffer b;
     838        gss_buffer_desc gssbuf;
     839        gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
     840        OM_uint32 ms;
     841
     842        static int attempt = 0;
     843        if (attempt++ >= 1)
     844                return (0);
     845
     846        if (gss_kex_context == NULL) {
     847                debug("No valid Key exchange context");
     848                return (0);
     849        }
     850
     851        ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
     852            "gssapi-keyex");
     853
     854        gssbuf.value = buffer_ptr(&b);
     855        gssbuf.length = buffer_len(&b);
     856
     857        if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
     858                buffer_free(&b);
     859                return (0);
     860        }
     861
     862        packet_start(SSH2_MSG_USERAUTH_REQUEST);
     863        packet_put_cstring(authctxt->server_user);
     864        packet_put_cstring(authctxt->service);
     865        packet_put_cstring(authctxt->method->name);
     866        packet_put_string(mic.value, mic.length);
     867        packet_send();
     868
     869        buffer_free(&b);
     870        gss_release_buffer(&ms, &mic);
     871
     872        return (1);
     873}
     874
    765875#endif /* GSSAPI */
    766876
    767877int
  • openssh-5.3p1

    old new  
    5353        int              valid;         /* user exists and is allowed to login */
    5454        int              attempt;
    5555        int              failures;
     56        int              server_caused_failure;
    5657        int              force_pwchange;
    5758        char            *user;          /* username sent by the client */
    5859        char            *service;
  • openssh-5.3p1

    old new  
    11/* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    5252static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
    5353static void input_gssapi_errtok(int, u_int32_t, void *);
    5454
     55/*
     56 * The 'gssapi_keyex' userauth mechanism.
     57 */
     58static int
     59userauth_gsskeyex(Authctxt *authctxt)
     60{
     61        int authenticated = 0;
     62        Buffer b;
     63        gss_buffer_desc mic, gssbuf;
     64        u_int len;
     65
     66        mic.value = packet_get_string(&len);
     67        mic.length = len;
     68
     69        packet_check_eom();
     70
     71        ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
     72            "gssapi-keyex");
     73
     74        gssbuf.value = buffer_ptr(&b);
     75        gssbuf.length = buffer_len(&b);
     76
     77        /* gss_kex_context is NULL with privsep, so we can't check it here */
     78        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
     79            &gssbuf, &mic))))
     80                authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
     81                    authctxt->pw));
     82       
     83        buffer_free(&b);
     84        xfree(mic.value);
     85
     86        return (authenticated);
     87}
     88
    5589/*
    5690 * We only support those mechanisms that we know about (ie ones that we know
    5791 * how to check local user kuserok and the like)
     
    102136
    103137        if (!present) {
    104138                xfree(doid);
     139                authctxt->server_caused_failure = 1;
    105140                return (0);
    106141        }
    107142
     
    109144                if (ctxt != NULL)
    110145                        ssh_gssapi_delete_ctx(&ctxt);
    111146                xfree(doid);
     147                authctxt->server_caused_failure = 1;
    112148                return (0);
    113149        }
    114150
     
    242278
    243279        packet_check_eom();
    244280
    245         authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
     281        authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
     282            authctxt->pw));
    246283
    247284        authctxt->postponed = 0;
    248285        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
     
    277314        gssbuf.length = buffer_len(&b);
    278315
    279316        if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
    280                 authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
     317                authenticated =
     318                    PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
    281319        else
    282320                logit("GSSAPI MIC check failed");
    283321
     
    292330        userauth_finish(authctxt, authenticated, "gssapi-with-mic");
    293331}
    294332
     333Authmethod method_gsskeyex = {
     334        "gssapi-keyex",
     335        userauth_gsskeyex,
     336        &options.gss_authentication
     337};
     338
    295339Authmethod method_gssapi = {
    296340        "gssapi-with-mic",
    297341        userauth_gssapi,
  • openssh-5.3p1

    old new  
    6969extern Authmethod method_kbdint;
    7070extern Authmethod method_hostbased;
    7171#ifdef GSSAPI
     72extern Authmethod method_gsskeyex;
    7273extern Authmethod method_gssapi;
    7374#endif
    7475#ifdef JPAKE
     
    7980        &method_none,
    8081        &method_pubkey,
    8182#ifdef GSSAPI
     83        &method_gsskeyex,
    8284        &method_gssapi,
    8385#endif
    8486#ifdef JPAKE
     
    274276#endif
    275277
    276278        authctxt->postponed = 0;
     279        authctxt->server_caused_failure = 0;
    277280
    278281        /* try to authenticate user */
    279282        m = authmethod_lookup(method);
     
    346349        } else {
    347350
    348351                /* Allow initial try of "none" auth without failure penalty */
    349                 if (authctxt->attempt > 1 || strcmp(method, "none") != 0)
     352                if (!authctxt->server_caused_failure &&
     353                    (authctxt->attempt > 1 || strcmp(method, "none") != 0))
    350354                        authctxt->failures++;
    351355                if (authctxt->failures >= options.max_authtries) {
    352356#ifdef SSH_AUDIT_EVENTS
  • openssh-5.3p1

    old new  
    166166
    167167        len = strlen(authctxt->krb5_ticket_file) + 6;
    168168        authctxt->krb5_ccname = xmalloc(len);
     169#ifdef USE_CCAPI
     170        snprintf(authctxt->krb5_ccname, len, "API:%s",
     171            authctxt->krb5_ticket_file);
     172#else
    169173        snprintf(authctxt->krb5_ccname, len, "FILE:%s",
    170174            authctxt->krb5_ticket_file);
     175#endif
    171176
    172177#ifdef USE_PAM
    173178        if (options.use_pam)
     
    219224#ifndef HEIMDAL
    220225krb5_error_code
    221226ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
    222         int tmpfd, ret;
     227        int ret;
    223228        char ccname[40];
    224229        mode_t old_umask;
     230#ifdef USE_CCAPI
     231        char cctemplate[] = "API:krb5cc_%d";
     232#else
     233        char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
     234        int tmpfd;
     235#endif
    225236
    226237        ret = snprintf(ccname, sizeof(ccname),
    227             "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
     238            cctemplate, geteuid());
    228239        if (ret < 0 || (size_t)ret >= sizeof(ccname))
    229240                return ENOMEM;
    230241
     242#ifndef USE_CCAPI
    231243        old_umask = umask(0177);
    232244        tmpfd = mkstemp(ccname + strlen("FILE:"));
    233245        umask(old_umask);
     
    242254                return errno;
    243255        }
    244256        close(tmpfd);
     257#endif
    245258
    246259        return (krb5_cc_resolve(ctx, ccname, ccache));
    247260}
  • gss-serv-krb5.c

    old new  
    11/* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    120120        krb5_principal princ;
    121121        OM_uint32 maj_status, min_status;
    122122        int len;
     123        const char *new_ccname;
    123124
    124125        if (client->creds == NULL) {
    125126                debug("No credentials stored");
     
    168169                return;
    169170        }
    170171
    171         client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
     172        new_ccname = krb5_cc_get_name(krb_context, ccache);
     173
    172174        client->store.envvar = "KRB5CCNAME";
    173         len = strlen(client->store.filename) + 6;
    174         client->store.envval = xmalloc(len);
    175         snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
     175#ifdef USE_CCAPI
     176        xasprintf(&client->store.envval, "API:%s", new_ccname);
     177        client->store.filename = NULL;
     178#else
     179        xasprintf(&client->store.envval, "FILE:%s", new_ccname);
     180        client->store.filename = xstrdup(new_ccname);
     181#endif
    176182
    177183#ifdef USE_PAM
    178184        if (options.use_pam)
     
    184190        return;
    185191}
    186192
     193int
     194ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
     195    ssh_gssapi_client *client)
     196{
     197        krb5_ccache ccache = NULL;
     198        krb5_principal principal = NULL;
     199        char *name = NULL;
     200        krb5_error_code problem;
     201        OM_uint32 maj_status, min_status;
     202
     203        if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
     204                logit("krb5_cc_resolve(): %.100s",
     205                    krb5_get_err_text(krb_context, problem));
     206                return 0;
     207        }
     208       
     209        /* Find out who the principal in this cache is */
     210        if ((problem = krb5_cc_get_principal(krb_context, ccache,
     211            &principal))) {
     212                logit("krb5_cc_get_principal(): %.100s",
     213                    krb5_get_err_text(krb_context, problem));
     214                krb5_cc_close(krb_context, ccache);
     215                return 0;
     216        }
     217
     218        if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
     219                logit("krb5_unparse_name(): %.100s",
     220                    krb5_get_err_text(krb_context, problem));
     221                krb5_free_principal(krb_context, principal);
     222                krb5_cc_close(krb_context, ccache);
     223                return 0;
     224        }
     225
     226
     227        if (strcmp(name,client->exportedname.value)!=0) {
     228                debug("Name in local credentials cache differs. Not storing");
     229                krb5_free_principal(krb_context, principal);
     230                krb5_cc_close(krb_context, ccache);
     231                krb5_free_unparsed_name(krb_context, name);
     232                return 0;
     233        }
     234        krb5_free_unparsed_name(krb_context, name);
     235
     236        /* Name matches, so lets get on with it! */
     237
     238        if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
     239                logit("krb5_cc_initialize(): %.100s",
     240                    krb5_get_err_text(krb_context, problem));
     241                krb5_free_principal(krb_context, principal);
     242                krb5_cc_close(krb_context, ccache);
     243                return 0;
     244        }
     245
     246        krb5_free_principal(krb_context, principal);
     247
     248        if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
     249            ccache))) {
     250                logit("gss_krb5_copy_ccache() failed. Sorry!");
     251                krb5_cc_close(krb_context, ccache);
     252                return 0;
     253        }
     254
     255        return 1;
     256}
     257
    187258ssh_gssapi_mech gssapi_kerberos_mech = {
    188259        "toWM5Slw5Ew8Mqkay+al2g==",
    189260        "Kerberos",
     
    191262        NULL,
    192263        &ssh_gssapi_krb5_userok,
    193264        NULL,
    194         &ssh_gssapi_krb5_storecreds
     265        &ssh_gssapi_krb5_storecreds,
     266        &ssh_gssapi_krb5_updatecreds
    195267};
    196268
    197269#endif /* KRB5 */
  • openssh-5.3p1

    old new  
    120120#include "roaming.h"
    121121#include "version.h"
    122122
     123#ifdef USE_SECURITY_SESSION_API
     124#include <Security/AuthSession.h>
     125#endif
     126
    123127#ifdef LIBWRAP
    124128#include <tcpd.h>
    125129#include <syslog.h>
     
    15311535                logit("Disabling protocol version 1. Could not load host key");
    15321536                options.protocol &= ~SSH_PROTO_1;
    15331537        }
     1538#ifndef GSSAPI
     1539        /* The GSSAPI key exchange can run without a host key */
    15341540        if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
    15351541                logit("Disabling protocol version 2. Could not load host key");
    15361542                options.protocol &= ~SSH_PROTO_2;
    15371543        }
     1544#endif
    15381545        if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
    15391546                logit("sshd: no hostkeys available -- exiting.");
    15401547                exit(1);
     
    18181825        /* Log the connection. */
    18191826        verbose("Connection from %.500s port %d", remote_ip, remote_port);
    18201827
     1828#ifdef USE_SECURITY_SESSION_API
     1829        /*
     1830         * Create a new security session for use by the new user login if
     1831         * the current session is the root session or we are not launched
     1832         * by inetd (eg: debugging mode or server mode).  We do not
     1833         * necessarily need to create a session if we are launched from
     1834         * inetd because Panther xinetd will create a session for us.
     1835         *
     1836         * The only case where this logic will fail is if there is an
     1837         * inetd running in a non-root session which is not creating
     1838         * new sessions for us.  Then all the users will end up in the
     1839         * same session (bad).
     1840         *
     1841         * When the client exits, the session will be destroyed for us
     1842         * automatically.
     1843         *
     1844         * We must create the session before any credentials are stored
     1845         * (including AFS pags, which happens a few lines below).
     1846         */
     1847        {
     1848                OSStatus err = 0;
     1849                SecuritySessionId sid = 0;
     1850                SessionAttributeBits sattrs = 0;
     1851
     1852                err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
     1853                if (err)
     1854                        error("SessionGetInfo() failed with error %.8X",
     1855                            (unsigned) err);
     1856                else
     1857                        debug("Current Session ID is %.8X / Session Attributes are %.8X",
     1858                            (unsigned) sid, (unsigned) sattrs);
     1859
     1860                if (inetd_flag && !(sattrs & sessionIsRoot))
     1861                        debug("Running in inetd mode in a non-root session... "
     1862                            "assuming inetd created the session for us.");
     1863                else {
     1864                        debug("Creating new security session...");
     1865                        err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
     1866                        if (err)
     1867                                error("SessionCreate() failed with error %.8X",
     1868                                    (unsigned) err);
     1869
     1870                        err = SessionGetInfo(callerSecuritySession, &sid,
     1871                            &sattrs);
     1872                        if (err)
     1873                                error("SessionGetInfo() failed with error %.8X",
     1874                                    (unsigned) err);
     1875                        else
     1876                                debug("New Session ID is %.8X / Session Attributes are %.8X",
     1877                                    (unsigned) sid, (unsigned) sattrs);
     1878                }
     1879        }
     1880#endif
     1881
    18211882        /*
    18221883         * We don't want to listen forever unless the other side
    18231884         * successfully authenticates itself.  So we set up an alarm which is
     
    21952256
    21962257        myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
    21972258
     2259#ifdef GSSAPI
     2260        {
     2261        char *orig;
     2262        char *gss = NULL;
     2263        char *newstr = NULL;
     2264        orig = myproposal[PROPOSAL_KEX_ALGS];
     2265
     2266        /*
     2267         * If we don't have a host key, then there's no point advertising
     2268         * the other key exchange algorithms
     2269         */
     2270
     2271        if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
     2272                orig = NULL;
     2273
     2274        if (options.gss_keyex)
     2275                gss = ssh_gssapi_server_mechanisms();
     2276        else
     2277                gss = NULL;
     2278
     2279        if (gss && orig)
     2280                xasprintf(&newstr, "%s,%s", gss, orig);
     2281        else if (gss)
     2282                newstr = gss;
     2283        else if (orig)
     2284                newstr = orig;
     2285
     2286        /*
     2287         * If we've got GSSAPI mechanisms, then we've got the 'null' host
     2288         * key alg, but we can't tell people about it unless its the only
     2289         * host key algorithm we support
     2290         */
     2291        if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
     2292                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
     2293
     2294        if (newstr)
     2295                myproposal[PROPOSAL_KEX_ALGS] = newstr;
     2296        else
     2297                fatal("No supported key exchange algorithms");
     2298        }
     2299#endif
     2300
    21982301        /* start key exchange */
    21992302        kex = kex_setup(myproposal);
    22002303        kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
    22012304        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
    22022305        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
    22032306        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
     2307#ifdef GSSAPI
     2308        if (options.gss_keyex) {
     2309                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
     2310                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
     2311                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
     2312        }
     2313#endif
    22042314        kex->server = 1;
    22052315        kex->client_version_string=client_version_string;
    22062316        kex->server_version_string=server_version_string;
  • configure.ac

    old new  
    477477            [Use tunnel device compatibility to OpenBSD])
    478478        AC_DEFINE(SSH_TUN_PREPEND_AF, 1,
    479479            [Prepend the address family to IP tunnel traffic])
     480        AC_MSG_CHECKING(if we have the Security Authorization Session API)
     481        AC_TRY_COMPILE([#include <Security/AuthSession.h>],
     482                [SessionCreate(0, 0);],
     483                [ac_cv_use_security_session_api="yes"
     484                 AC_DEFINE(USE_SECURITY_SESSION_API, 1,
     485                        [platform has the Security Authorization Session API])
     486                 LIBS="$LIBS -framework Security"
     487                 AC_MSG_RESULT(yes)],
     488                [ac_cv_use_security_session_api="no"
     489                 AC_MSG_RESULT(no)])
     490        AC_MSG_CHECKING(if we have an in-memory credentials cache)
     491        AC_TRY_COMPILE(
     492                [#include <Kerberos/Kerberos.h>],
     493                [cc_context_t c;
     494                 (void) cc_initialize (&c, 0, NULL, NULL);],
     495                [AC_DEFINE(USE_CCAPI, 1,
     496                        [platform uses an in-memory credentials cache])
     497                 LIBS="$LIBS -framework Security"
     498                 AC_MSG_RESULT(yes)
     499                 if test "x$ac_cv_use_security_session_api" = "xno"; then
     500                        AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
     501                fi],
     502                [AC_MSG_RESULT(no)]
     503        )
    480504        m4_pattern_allow(AU_IPv)
    481505        AC_CHECK_DECL(AU_IPv4, [],
    482506            AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records])
  • new file openssh-5.3p1/ChangeLog.gssapi

    - +  
     120100124
     2  - [ sshconnect2.c ]
     3    Adapt to deal with additional element in Authmethod structure. Thanks to
     4    Colin Watson
     5  - [ clientloop.c ]
     6    Protect credentials updated code with suitable #ifdefs. Thanks to Colin
     7    Watson
     8
     920090615
     10  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
     11      sshd.c ]
     12    Fix issues identified by Greg Hudson following a code review
     13        Check return value of gss_indicate_mechs
     14        Protect GSSAPI calls in monitor, so they can only be used if enabled
     15        Check return values of bignum functions in key exchange
     16        Use BN_clear_free to clear other side's DH value
     17        Make ssh_gssapi_id_kex more robust
     18        Only configure kex table pointers if GSSAPI is enabled
     19        Don't leak mechanism list, or gss mechanism list
     20        Cast data.length before printing
     21        If serverkey isn't provided, use an empty string, rather than NULL
     22
     2320090201
     24  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
     25      ssh_config.5 sshconnet2.c ]
     26    Add support for the GSSAPIClientIdentity option, which allows the user
     27    to specify which GSSAPI identity to use to contact a given server
     28
     2920080404
     30  - [ gss-serv.c ]
     31    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
     32    been omitted from a previous version of this patch. Reported by Borislav
     33    Stoichkov
     34
     3520070317
     36  - [ gss-serv-krb5.c ]
     37    Remove C99ism, where new_ccname was being declared in the middle of a
     38    function
     39
     4020061220
     41  - [ servconf.c ]
     42    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
     43    documented, behaviour. Reported by Dan Watson.
     44
     4520060910
     46  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
     47      ssh-gss.h ]
     48    add support for gss-group14-sha1 key exchange mechanisms
     49  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
     50    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
     51    acceptor principal checking on multi-homed machines.
     52    <Bugzilla #928>
     53  - [ sshd_config ssh_config ]
     54    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
     55    configuration files
     56  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
     57    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
     58    Limit length of error messages displayed by client
     59
     6020060909
     61  - [ gss-genr.c gss-serv.c ]
     62    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
     63    only, where they belong
     64    <Bugzilla #1225>
     65
     6620060829
     67  - [ gss-serv-krb5.c ]
     68    Fix CCAPI credentials cache name when creating KRB5CCNAME environment
     69    variable
     70
     7120060828
     72  - [ gss-genr.c ]
     73    Avoid Heimdal context freeing problem
     74    <Fixed upstream 20060829>
     75
     7620060818
     77  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
     78    Make sure that SPENGO is disabled
     79    <Bugzilla #1218 - Fixed upstream 20060818>
     80
     8120060421
     82  - [ gssgenr.c, sshconnect2.c ]
     83    a few type changes (signed versus unsigned, int versus size_t) to
     84    fix compiler errors/warnings
     85    (from jbasney AT ncsa.uiuc.edu)
     86  - [ kexgssc.c, sshconnect2.c ]
     87    fix uninitialized variable warnings
     88    (from jbasney AT ncsa.uiuc.edu)
     89  - [ gssgenr.c ]
     90    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
     91    (from jbasney AT ncsa.uiuc.edu)
     92    <Bugzilla #1220 >
     93  - [ gss-serv-krb5.c ]
     94    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
     95    (from jbasney AT ncsa.uiuc.edu)
     96    <Fixed upstream 20060304>
     97  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
     98    add client-side GssapiKeyExchange option
     99    (from jbasney AT ncsa.uiuc.edu)
     100  - [ sshconnect2.c ]
     101    add support for GssapiTrustDns option for gssapi-with-mic
     102    (from jbasney AT ncsa.uiuc.edu)
     103    <gssapi-with-mic support is Bugzilla #1008>
  • openssh-5.3p1

    old new LIBSSH_OBJS=acss.o authfd.o authfile.o b 
    7474        monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
    7575        kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \
    7676        entropy.o gss-genr.o umac.o jpake.o schnorr.o \
    77         ssh-pkcs11.o
     77        ssh-pkcs11.o kexgssc.o
    7878
    7979SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
    8080        sshconnect.o sshconnect1.o sshconnect2.o mux.o \
     
    8586        auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
    8687        monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
    8788        auth-krb5.o \
    88         auth2-gss.o gss-serv.o gss-serv-krb5.o \
     89        auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
    8990        loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
    9091        audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
    9192        roaming_common.o
  • openssh-5.3p1

    old new  
    11/* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
    22
    33/*
    4  * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
     4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    55 *
    66 * Redistribution and use in source and binary forms, with or without
    77 * modification, are permitted provided that the following conditions
     
    3939#include "buffer.h"
    4040#include "log.h"
    4141#include "ssh2.h"
     42#include "cipher.h"
     43#include "key.h"
     44#include "kex.h"
     45#include <openssl/evp.h>
    4246
    4347#include "ssh-gss.h"
    4448
    4549extern u_char *session_id2;
    4650extern u_int session_id2_len;
    4751
     52typedef struct {
     53        char *encoded;
     54        gss_OID oid;
     55} ssh_gss_kex_mapping;
     56
     57/*
     58 * XXX - It would be nice to find a more elegant way of handling the
     59 * XXX   passing of the key exchange context to the userauth routines
     60 */
     61
     62Gssctxt *gss_kex_context = NULL;
     63
     64static ssh_gss_kex_mapping *gss_enc2oid = NULL;
     65
     66int
     67ssh_gssapi_oid_table_ok() {
     68        return (gss_enc2oid != NULL);
     69}
     70
     71/*
     72 * Return a list of the gss-group1-sha1 mechanisms supported by this program
     73 *
     74 * We test mechanisms to ensure that we can use them, to avoid starting
     75 * a key exchange with a bad mechanism
     76 */
     77
     78char *
     79ssh_gssapi_client_mechanisms(const char *host, const char *client) {
     80        gss_OID_set gss_supported;
     81        OM_uint32 min_status;
     82
     83        if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
     84                return NULL;
     85
     86        return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
     87            host, client));
     88}
     89
     90char *
     91ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
     92    const char *host, const char *client) {
     93        Buffer buf;
     94        size_t i;
     95        int oidpos, enclen;
     96        char *mechs, *encoded;
     97        u_char digest[EVP_MAX_MD_SIZE];
     98        char deroid[2];
     99        const EVP_MD *evp_md = EVP_md5();
     100        EVP_MD_CTX md;
     101
     102        if (gss_enc2oid != NULL) {
     103                for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
     104                        xfree(gss_enc2oid[i].encoded);
     105                xfree(gss_enc2oid);
     106        }
     107
     108        gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
     109            (gss_supported->count + 1));
     110
     111        buffer_init(&buf);
     112
     113        oidpos = 0;
     114        for (i = 0; i < gss_supported->count; i++) {
     115                if (gss_supported->elements[i].length < 128 &&
     116                    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
     117
     118                        deroid[0] = SSH_GSS_OIDTYPE;
     119                        deroid[1] = gss_supported->elements[i].length;
     120
     121                        EVP_DigestInit(&md, evp_md);
     122                        EVP_DigestUpdate(&md, deroid, 2);
     123                        EVP_DigestUpdate(&md,
     124                            gss_supported->elements[i].elements,
     125                            gss_supported->elements[i].length);
     126                        EVP_DigestFinal(&md, digest, NULL);
     127
     128                        encoded = xmalloc(EVP_MD_size(evp_md) * 2);
     129                        enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
     130                            encoded, EVP_MD_size(evp_md) * 2);
     131
     132                        if (oidpos != 0)
     133                                buffer_put_char(&buf, ',');
     134
     135                        buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
     136                            sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
     137                        buffer_append(&buf, encoded, enclen);
     138                        buffer_put_char(&buf, ',');
     139                        buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID,
     140                            sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
     141                        buffer_append(&buf, encoded, enclen);
     142                        buffer_put_char(&buf, ',');
     143                        buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
     144                            sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
     145                        buffer_append(&buf, encoded, enclen);
     146
     147                        gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
     148                        gss_enc2oid[oidpos].encoded = encoded;
     149                        oidpos++;
     150                }
     151        }
     152        gss_enc2oid[oidpos].oid = NULL;
     153        gss_enc2oid[oidpos].encoded = NULL;
     154
     155        buffer_put_char(&buf, '\0');
     156
     157        mechs = xmalloc(buffer_len(&buf));
     158        buffer_get(&buf, mechs, buffer_len(&buf));
     159        buffer_free(&buf);
     160
     161        if (strlen(mechs) == 0) {
     162                xfree(mechs);
     163                mechs = NULL;
     164        }
     165       
     166        return (mechs);
     167}
     168
     169gss_OID
     170ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
     171        int i = 0;
     172       
     173        switch (kex_type) {
     174        case KEX_GSS_GRP1_SHA1:
     175                if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
     176                        return GSS_C_NO_OID;
     177                name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
     178                break;
     179        case KEX_GSS_GRP14_SHA1:
     180                if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
     181                        return GSS_C_NO_OID;
     182                name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
     183                break;
     184        case KEX_GSS_GEX_SHA1:
     185                if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
     186                        return GSS_C_NO_OID;
     187                name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
     188                break;
     189        default:
     190                return GSS_C_NO_OID;
     191        }
     192
     193        while (gss_enc2oid[i].encoded != NULL &&
     194            strcmp(name, gss_enc2oid[i].encoded) != 0)
     195                i++;
     196
     197        if (gss_enc2oid[i].oid != NULL && ctx != NULL)
     198                ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
     199
     200        return gss_enc2oid[i].oid;
     201}
     202
    48203/* Check that the OID in a data stream matches that in the context */
    49204int
    50205ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
     
    197352        }
    198353
    199354        ctx->major = gss_init_sec_context(&ctx->minor,
    200             GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
     355            ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
    201356            GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
    202357            0, NULL, recv_tok, NULL, send_tok, flags, NULL);
    203358
     
    227382}
    228383
    229384OM_uint32
     385ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
     386{
     387        gss_buffer_desc gssbuf;
     388        gss_name_t gssname;
     389        OM_uint32 status;
     390        gss_OID_set oidset;
     391
     392        gssbuf.value = (void *) name;
     393        gssbuf.length = strlen(gssbuf.value);
     394
     395        gss_create_empty_oid_set(&status, &oidset);
     396        gss_add_oid_set_member(&status, ctx->oid, &oidset);
     397
     398        ctx->major = gss_import_name(&ctx->minor, &gssbuf,
     399            GSS_C_NT_USER_NAME, &gssname);
     400
     401        if (!ctx->major)
     402                ctx->major = gss_acquire_cred(&ctx->minor,
     403                    gssname, 0, oidset, GSS_C_INITIATE,
     404                    &ctx->client_creds, NULL, NULL);
     405
     406        gss_release_name(&status, &gssname);
     407        gss_release_oid_set(&status, &oidset);
     408
     409        if (ctx->major)
     410                ssh_gssapi_error(ctx);
     411
     412        return(ctx->major);
     413}
     414
     415OM_uint32
    230416ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
    231417{
     418        if (ctx == NULL)
     419                return -1;
     420
    232421        if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
    233422            GSS_C_QOP_DEFAULT, buffer, hash)))
    234423                ssh_gssapi_error(ctx);
     
    236425        return (ctx->major);
    237426}
    238427
     428/* Priviledged when used by server */
     429OM_uint32
     430ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
     431{
     432        if (ctx == NULL)
     433                return -1;
     434
     435        ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
     436            gssbuf, gssmic, NULL);
     437
     438        return (ctx->major);
     439}
     440
    239441void
    240442ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
    241443    const char *context)
     
    249451}
    250452
    251453int
    252 ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
     454ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host,
     455    const char *client)
    253456{
    254457        gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
    255458        OM_uint32 major, minor;
    256459        gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
     460        Gssctxt *intctx = NULL;
     461
     462        if (ctx == NULL)
     463                ctx = &intctx;
    257464
    258465        /* RFC 4462 says we MUST NOT do SPNEGO */
    259466        if (oid->length == spnego_oid.length &&
     
    263470        ssh_gssapi_build_ctx(ctx);
    264471        ssh_gssapi_set_oid(*ctx, oid);
    265472        major = ssh_gssapi_import_name(*ctx, host);
     473
     474        if (!GSS_ERROR(major) && client)
     475                major = ssh_gssapi_client_identity(*ctx, client);
     476
    266477        if (!GSS_ERROR(major)) {
    267478                major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
    268479                    NULL);
     
    272483                            GSS_C_NO_BUFFER);
    273484        }
    274485
    275         if (GSS_ERROR(major))
     486        if (GSS_ERROR(major) || intctx != NULL)
    276487                ssh_gssapi_delete_ctx(ctx);
    277488
    278489        return (!GSS_ERROR(major));
    279490}
    280491
     492int
     493ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
     494        static gss_name_t saved_name = GSS_C_NO_NAME;
     495        static OM_uint32 saved_lifetime = 0;
     496        static gss_OID saved_mech = GSS_C_NO_OID;
     497        static gss_name_t name;
     498        static OM_uint32 last_call = 0;
     499        OM_uint32 lifetime, now, major, minor;
     500        int equal;
     501        gss_cred_usage_t usage = GSS_C_INITIATE;
     502       
     503        now = time(NULL);
     504
     505        if (ctxt) {
     506                debug("Rekey has happened - updating saved versions");
     507
     508                if (saved_name != GSS_C_NO_NAME)
     509                        gss_release_name(&minor, &saved_name);
     510
     511                major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
     512                    &saved_name, &saved_lifetime, NULL, NULL);
     513
     514                if (!GSS_ERROR(major)) {
     515                        saved_mech = ctxt->oid;
     516                        saved_lifetime+= now;
     517                } else {
     518                        /* Handle the error */
     519                }
     520                return 0;
     521        }
     522
     523        if (now - last_call < 10)
     524                return 0;
     525
     526        last_call = now;
     527
     528        if (saved_mech == GSS_C_NO_OID)
     529                return 0;
     530       
     531        major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
     532            &name, &lifetime, NULL, NULL);
     533        if (major == GSS_S_CREDENTIALS_EXPIRED)
     534                return 0;
     535        else if (GSS_ERROR(major))
     536                return 0;
     537
     538        major = gss_compare_name(&minor, saved_name, name, &equal);
     539        gss_release_name(&minor, &name);
     540        if (GSS_ERROR(major))
     541                return 0;
     542
     543        if (equal && (saved_lifetime < lifetime + now - 10))
     544                return 1;
     545
     546        return 0;
     547}
     548
    281549#endif /* GSSAPI */
  • openssh-5.3p1

    old new  
    4949#include "dispatch.h"
    5050#include "monitor.h"
    5151
     52#ifdef GSSAPI
     53#include "ssh-gss.h"
     54#endif
     55
    5256#if OPENSSL_VERSION_NUMBER >= 0x00907000L
    5357# if defined(HAVE_EVP_SHA256)
    5458# define evp_ssh_sha256 EVP_sha256
     
    325329                k->kex_type = KEX_DH_GEX_SHA256;
    326330                k->evp_md = evp_ssh_sha256();
    327331#endif
     332#ifdef GSSAPI
     333        } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
     334            sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
     335                k->kex_type = KEX_GSS_GEX_SHA1;
     336                k->evp_md = EVP_sha1();
     337        } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
     338            sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
     339                k->kex_type = KEX_GSS_GRP1_SHA1;
     340                k->evp_md = EVP_sha1();
     341        } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
     342            sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
     343                k->kex_type = KEX_GSS_GRP14_SHA1;
     344                k->evp_md = EVP_sha1();
     345#endif
    328346        } else
    329347                fatal("bad kex alg %s", k->name);
    330348}
  • openssh-5.3p1

    old new  
    6666        KEX_DH_GRP14_SHA1,
    6767        KEX_DH_GEX_SHA1,
    6868        KEX_DH_GEX_SHA256,
     69        KEX_GSS_GRP1_SHA1,
     70        KEX_GSS_GRP14_SHA1,
     71        KEX_GSS_GEX_SHA1,
    6972        KEX_MAX
    7073};
    7174
     
    121124        sig_atomic_t done;
    122125        int     flags;
    123126        const EVP_MD *evp_md;
     127#ifdef GSSAPI
     128        int     gss_deleg_creds;
     129        int     gss_trust_dns;
     130        char    *gss_host;
     131        char    *gss_client;
     132#endif
    124133        char    *client_version_string;
    125134        char    *server_version_string;
    126135        int     (*verify_host_key)(Key *);
     
    143152void     kexgex_client(Kex *);
    144153void     kexgex_server(Kex *);
    145154
     155#ifdef GSSAPI
     156void    kexgss_client(Kex *);
     157void    kexgss_server(Kex *);
     158#endif
     159
    146160void
    147161kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
    148162    BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
  • new file openssh-5.3p1/kexgssc.c

    - +  
     1/*
     2 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
     3 *
     4 * Redistribution and use in source and binary forms, with or without
     5 * modification, are permitted provided that the following conditions
     6 * are met:
     7 * 1. Redistributions of source code must retain the above copyright
     8 *    notice, this list of conditions and the following disclaimer.
     9 * 2. Redistributions in binary form must reproduce the above copyright
     10 *    notice, this list of conditions and the following disclaimer in the
     11 *    documentation and/or other materials provided with the distribution.
     12 *
     13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
     14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 */
     24
     25#include "includes.h"
     26
     27#ifdef GSSAPI
     28
     29#include "includes.h"
     30
     31#include <openssl/crypto.h>
     32#include <openssl/bn.h>
     33
     34#include <string.h>
     35
     36#include "xmalloc.h"
     37#include "buffer.h"
     38#include "ssh2.h"
     39#include "key.h"
     40#include "cipher.h"
     41#include "kex.h"
     42#include "log.h"
     43#include "packet.h"
     44#include "dh.h"
     45
     46#include "ssh-gss.h"
     47
     48void
     49kexgss_client(Kex *kex) {
     50        gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
     51        gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
     52        Gssctxt *ctxt;
     53        OM_uint32 maj_status, min_status, ret_flags;
     54        u_int klen, kout, slen = 0, hashlen, strlen;
     55        DH *dh;
     56        BIGNUM *dh_server_pub = NULL;
     57        BIGNUM *shared_secret = NULL;
     58        BIGNUM *p = NULL;
     59        BIGNUM *g = NULL;       
     60        u_char *kbuf, *hash;
     61        u_char *serverhostkey = NULL;
     62        u_char *empty = "";
     63        char *msg;
     64        char *lang;
     65        int type = 0;
     66        int first = 1;
     67        int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
     68
     69        /* Initialise our GSSAPI world */       
     70        ssh_gssapi_build_ctx(&ctxt);
     71        if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
     72            == GSS_C_NO_OID)
     73                fatal("Couldn't identify host exchange");
     74
     75        if (ssh_gssapi_import_name(ctxt, kex->gss_host))
     76                fatal("Couldn't import hostname");
     77
     78        if (kex->gss_client &&
     79            ssh_gssapi_client_identity(ctxt, kex->gss_client))
     80                fatal("Couldn't acquire client credentials");
     81
     82        switch (kex->kex_type) {
     83        case KEX_GSS_GRP1_SHA1:
     84                dh = dh_new_group1();
     85                break;
     86        case KEX_GSS_GRP14_SHA1:
     87                dh = dh_new_group14();
     88                break;
     89        case KEX_GSS_GEX_SHA1:
     90                debug("Doing group exchange\n");
     91                nbits = dh_estimate(kex->we_need * 8);
     92                packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
     93                packet_put_int(min);
     94                packet_put_int(nbits);
     95                packet_put_int(max);
     96
     97                packet_send();
     98
     99                packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
     100
     101                if ((p = BN_new()) == NULL)
     102                        fatal("BN_new() failed");
     103                packet_get_bignum2(p);
     104                if ((g = BN_new()) == NULL)
     105                        fatal("BN_new() failed");
     106                packet_get_bignum2(g);
     107                packet_check_eom();
     108
     109                if (BN_num_bits(p) < min || BN_num_bits(p) > max)
     110                        fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
     111                            min, BN_num_bits(p), max);
     112
     113                dh = dh_new_group(g, p);
     114                break;
     115        default:
     116                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     117        }
     118       
     119        /* Step 1 - e is dh->pub_key */
     120        dh_gen_key(dh, kex->we_need * 8);
     121
     122        /* This is f, we initialise it now to make life easier */
     123        dh_server_pub = BN_new();
     124        if (dh_server_pub == NULL)
     125                fatal("dh_server_pub == NULL");
     126
     127        token_ptr = GSS_C_NO_BUFFER;
     128                         
     129        do {
     130                debug("Calling gss_init_sec_context");
     131               
     132                maj_status = ssh_gssapi_init_ctx(ctxt,
     133                    kex->gss_deleg_creds, token_ptr, &send_tok,
     134                    &ret_flags);
     135
     136                if (GSS_ERROR(maj_status)) {
     137                        if (send_tok.length != 0) {
     138                                packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     139                                packet_put_string(send_tok.value,
     140                                    send_tok.length);
     141                        }
     142                        fatal("gss_init_context failed");
     143                }
     144
     145                /* If we've got an old receive buffer get rid of it */
     146                if (token_ptr != GSS_C_NO_BUFFER)
     147                        xfree(recv_tok.value);
     148
     149                if (maj_status == GSS_S_COMPLETE) {
     150                        /* If mutual state flag is not true, kex fails */
     151                        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
     152                                fatal("Mutual authentication failed");
     153
     154                        /* If integ avail flag is not true kex fails */
     155                        if (!(ret_flags & GSS_C_INTEG_FLAG))
     156                                fatal("Integrity check failed");
     157                }
     158
     159                /*
     160                 * If we have data to send, then the last message that we
     161                 * received cannot have been a 'complete'.
     162                 */
     163                if (send_tok.length != 0) {
     164                        if (first) {
     165                                packet_start(SSH2_MSG_KEXGSS_INIT);
     166                                packet_put_string(send_tok.value,
     167                                    send_tok.length);
     168                                packet_put_bignum2(dh->pub_key);
     169                                first = 0;
     170                        } else {
     171                                packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     172                                packet_put_string(send_tok.value,
     173                                    send_tok.length);
     174                        }
     175                        packet_send();
     176                        gss_release_buffer(&min_status, &send_tok);
     177
     178                        /* If we've sent them data, they should reply */
     179                        do {   
     180                                type = packet_read();
     181                                if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
     182                                        debug("Received KEXGSS_HOSTKEY");
     183                                        if (serverhostkey)
     184                                                fatal("Server host key received more than once");
     185                                        serverhostkey =
     186                                            packet_get_string(&slen);
     187                                }
     188                        } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
     189
     190                        switch (type) {
     191                        case SSH2_MSG_KEXGSS_CONTINUE:
     192                                debug("Received GSSAPI_CONTINUE");
     193                                if (maj_status == GSS_S_COMPLETE)
     194                                        fatal("GSSAPI Continue received from server when complete");
     195                                recv_tok.value = packet_get_string(&strlen);
     196                                recv_tok.length = strlen;
     197                                break;
     198                        case SSH2_MSG_KEXGSS_COMPLETE:
     199                                debug("Received GSSAPI_COMPLETE");
     200                                packet_get_bignum2(dh_server_pub);
     201                                msg_tok.value =  packet_get_string(&strlen);
     202                                msg_tok.length = strlen;
     203
     204                                /* Is there a token included? */
     205                                if (packet_get_char()) {
     206                                        recv_tok.value=
     207                                            packet_get_string(&strlen);
     208                                        recv_tok.length = strlen;
     209                                        /* If we're already complete - protocol error */
     210                                        if (maj_status == GSS_S_COMPLETE)
     211                                                packet_disconnect("Protocol error: received token when complete");
     212                                        } else {
     213                                                /* No token included */
     214                                                if (maj_status != GSS_S_COMPLETE)
     215                                                        packet_disconnect("Protocol error: did not receive final token");
     216                                }
     217                                break;
     218                        case SSH2_MSG_KEXGSS_ERROR:
     219                                debug("Received Error");
     220                                maj_status = packet_get_int();
     221                                min_status = packet_get_int();
     222                                msg = packet_get_string(NULL);
     223                                lang = packet_get_string(NULL);
     224                                fatal("GSSAPI Error: \n%.400s",msg);
     225                        default:
     226                                packet_disconnect("Protocol error: didn't expect packet type %d",
     227                                type);
     228                        }
     229                        token_ptr = &recv_tok;
     230                } else {
     231                        /* No data, and not complete */
     232                        if (maj_status != GSS_S_COMPLETE)
     233                                fatal("Not complete, and no token output");
     234                }
     235        } while (maj_status & GSS_S_CONTINUE_NEEDED);
     236
     237        /*
     238         * We _must_ have received a COMPLETE message in reply from the
     239         * server, which will have set dh_server_pub and msg_tok
     240         */
     241
     242        if (type != SSH2_MSG_KEXGSS_COMPLETE)
     243                fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
     244
     245        /* Check f in range [1, p-1] */
     246        if (!dh_pub_is_valid(dh, dh_server_pub))
     247                packet_disconnect("bad server public DH value");
     248
     249        /* compute K=f^x mod p */
     250        klen = DH_size(dh);
     251        kbuf = xmalloc(klen);
     252        kout = DH_compute_key(kbuf, dh_server_pub, dh);
     253        if (kout < 0)
     254                fatal("DH_compute_key: failed");
     255
     256        shared_secret = BN_new();
     257        if (shared_secret == NULL)
     258                fatal("kexgss_client: BN_new failed");
     259
     260        if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
     261                fatal("kexdh_client: BN_bin2bn failed");
     262
     263        memset(kbuf, 0, klen);
     264        xfree(kbuf);
     265
     266        switch (kex->kex_type) {
     267        case KEX_GSS_GRP1_SHA1:
     268        case KEX_GSS_GRP14_SHA1:
     269                kex_dh_hash( kex->client_version_string,
     270                    kex->server_version_string,
     271                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     272                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     273                    (serverhostkey ? serverhostkey : empty), slen,
     274                    dh->pub_key,        /* e */
     275                    dh_server_pub,      /* f */
     276                    shared_secret,      /* K */
     277                    &hash, &hashlen
     278                );
     279                break;
     280        case KEX_GSS_GEX_SHA1:
     281                kexgex_hash(
     282                    kex->evp_md,
     283                    kex->client_version_string,
     284                    kex->server_version_string,
     285                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     286                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     287                    (serverhostkey ? serverhostkey : empty), slen,
     288                    min, nbits, max,
     289                    dh->p, dh->g,
     290                    dh->pub_key,
     291                    dh_server_pub,
     292                    shared_secret,
     293                    &hash, &hashlen
     294                );
     295                break;
     296        default:
     297                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     298        }
     299
     300        gssbuf.value = hash;
     301        gssbuf.length = hashlen;
     302
     303        /* Verify that the hash matches the MIC we just got. */
     304        if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
     305                packet_disconnect("Hash's MIC didn't verify");
     306
     307        xfree(msg_tok.value);
     308
     309        DH_free(dh);
     310        if (serverhostkey)
     311                xfree(serverhostkey);
     312        BN_clear_free(dh_server_pub);
     313
     314        /* save session id */
     315        if (kex->session_id == NULL) {
     316                kex->session_id_len = hashlen;
     317                kex->session_id = xmalloc(kex->session_id_len);
     318                memcpy(kex->session_id, hash, kex->session_id_len);
     319        }
     320
     321        if (kex->gss_deleg_creds)
     322                ssh_gssapi_credentials_updated(ctxt);
     323
     324        if (gss_kex_context == NULL)
     325                gss_kex_context = ctxt;
     326        else
     327                ssh_gssapi_delete_ctx(&ctxt);
     328
     329        kex_derive_keys(kex, hash, hashlen, shared_secret);
     330        BN_clear_free(shared_secret);
     331        kex_finish(kex);
     332}
     333
     334#endif /* GSSAPI */
  • new file openssh-5.3p1/kexgsss.c

    - +  
     1/*
     2 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
     3 *
     4 * Redistribution and use in source and binary forms, with or without
     5 * modification, are permitted provided that the following conditions
     6 * are met:
     7 * 1. Redistributions of source code must retain the above copyright
     8 *    notice, this list of conditions and the following disclaimer.
     9 * 2. Redistributions in binary form must reproduce the above copyright
     10 *    notice, this list of conditions and the following disclaimer in the
     11 *    documentation and/or other materials provided with the distribution.
     12 *
     13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
     14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23 */
     24
     25#include "includes.h"
     26
     27#ifdef GSSAPI
     28
     29#include <string.h>
     30
     31#include <openssl/crypto.h>
     32#include <openssl/bn.h>
     33
     34#include "xmalloc.h"
     35#include "buffer.h"
     36#include "ssh2.h"
     37#include "key.h"
     38#include "cipher.h"
     39#include "kex.h"
     40#include "log.h"
     41#include "packet.h"
     42#include "dh.h"
     43#include "ssh-gss.h"
     44#include "monitor_wrap.h"
     45#include "servconf.h"
     46
     47extern ServerOptions options;
     48
     49void
     50kexgss_server(Kex *kex)
     51{
     52        OM_uint32 maj_status, min_status;
     53       
     54        /*
     55         * Some GSSAPI implementations use the input value of ret_flags (an
     56         * output variable) as a means of triggering mechanism specific
     57         * features. Initializing it to zero avoids inadvertently
     58         * activating this non-standard behaviour.
     59         */
     60
     61        OM_uint32 ret_flags = 0;
     62        gss_buffer_desc gssbuf, recv_tok, msg_tok;
     63        gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
     64        Gssctxt *ctxt = NULL;
     65        u_int slen, klen, kout, hashlen;
     66        u_char *kbuf, *hash;
     67        DH *dh;
     68        int min = -1, max = -1, nbits = -1;
     69        BIGNUM *shared_secret = NULL;
     70        BIGNUM *dh_client_pub = NULL;
     71        int type = 0;
     72        gss_OID oid;
     73        char *mechs;
     74
     75        /* Initialise GSSAPI */
     76
     77        /* If we're rekeying, privsep means that some of the private structures
     78         * in the GSSAPI code are no longer available. This kludges them back
     79         * into life
     80         */
     81        if (!ssh_gssapi_oid_table_ok())
     82                if ((mechs = ssh_gssapi_server_mechanisms()))
     83                        xfree(mechs);
     84
     85        debug2("%s: Identifying %s", __func__, kex->name);
     86        oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
     87        if (oid == GSS_C_NO_OID)
     88           fatal("Unknown gssapi mechanism");
     89
     90        debug2("%s: Acquiring credentials", __func__);
     91
     92        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
     93                fatal("Unable to acquire credentials for the server");
     94
     95        switch (kex->kex_type) {
     96        case KEX_GSS_GRP1_SHA1:
     97                dh = dh_new_group1();
     98                break;
     99        case KEX_GSS_GRP14_SHA1:
     100                dh = dh_new_group14();
     101                break;
     102        case KEX_GSS_GEX_SHA1:
     103                debug("Doing group exchange");
     104                packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
     105                min = packet_get_int();
     106                nbits = packet_get_int();
     107                max = packet_get_int();
     108                min = MAX(DH_GRP_MIN, min);
     109                max = MIN(DH_GRP_MAX, max);
     110                packet_check_eom();
     111                if (max < min || nbits < min || max < nbits)
     112                        fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
     113                            min, nbits, max);
     114                dh = PRIVSEP(choose_dh(min, nbits, max));
     115                if (dh == NULL)
     116                        packet_disconnect("Protocol error: no matching group found");
     117
     118                packet_start(SSH2_MSG_KEXGSS_GROUP);
     119                packet_put_bignum2(dh->p);
     120                packet_put_bignum2(dh->g);
     121                packet_send();
     122
     123                packet_write_wait();
     124                break;
     125        default:
     126                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     127        }
     128
     129        dh_gen_key(dh, kex->we_need * 8);
     130
     131        do {
     132                debug("Wait SSH2_MSG_GSSAPI_INIT");
     133                type = packet_read();
     134                switch(type) {
     135                case SSH2_MSG_KEXGSS_INIT:
     136                        if (dh_client_pub != NULL)
     137                                fatal("Received KEXGSS_INIT after initialising");
     138                        recv_tok.value = packet_get_string(&slen);
     139                        recv_tok.length = slen;
     140
     141                        if ((dh_client_pub = BN_new()) == NULL)
     142                                fatal("dh_client_pub == NULL");
     143
     144                        packet_get_bignum2(dh_client_pub);
     145
     146                        /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
     147                        break;
     148                case SSH2_MSG_KEXGSS_CONTINUE:
     149                        recv_tok.value = packet_get_string(&slen);
     150                        recv_tok.length = slen;
     151                        break;
     152                default:
     153                        packet_disconnect(
     154                            "Protocol error: didn't expect packet type %d",
     155                            type);
     156                }
     157
     158                maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
     159                    &send_tok, &ret_flags));
     160
     161                xfree(recv_tok.value);
     162
     163                if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
     164                        fatal("Zero length token output when incomplete");
     165
     166                if (dh_client_pub == NULL)
     167                        fatal("No client public key");
     168               
     169                if (maj_status & GSS_S_CONTINUE_NEEDED) {
     170                        debug("Sending GSSAPI_CONTINUE");
     171                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     172                        packet_put_string(send_tok.value, send_tok.length);
     173                        packet_send();
     174                        gss_release_buffer(&min_status, &send_tok);
     175                }
     176        } while (maj_status & GSS_S_CONTINUE_NEEDED);
     177
     178        if (GSS_ERROR(maj_status)) {
     179                if (send_tok.length > 0) {
     180                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
     181                        packet_put_string(send_tok.value, send_tok.length);
     182                        packet_send();
     183                }
     184                fatal("accept_ctx died");
     185        }
     186
     187        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
     188                fatal("Mutual Authentication flag wasn't set");
     189
     190        if (!(ret_flags & GSS_C_INTEG_FLAG))
     191                fatal("Integrity flag wasn't set");
     192       
     193        if (!dh_pub_is_valid(dh, dh_client_pub))
     194                packet_disconnect("bad client public DH value");
     195
     196        klen = DH_size(dh);
     197        kbuf = xmalloc(klen);
     198        kout = DH_compute_key(kbuf, dh_client_pub, dh);
     199        if (kout < 0)
     200                fatal("DH_compute_key: failed");
     201
     202        shared_secret = BN_new();
     203        if (shared_secret == NULL)
     204                fatal("kexgss_server: BN_new failed");
     205
     206        if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
     207                fatal("kexgss_server: BN_bin2bn failed");
     208
     209        memset(kbuf, 0, klen);
     210        xfree(kbuf);
     211
     212        switch (kex->kex_type) {
     213        case KEX_GSS_GRP1_SHA1:
     214        case KEX_GSS_GRP14_SHA1:
     215                kex_dh_hash(
     216                    kex->client_version_string, kex->server_version_string,
     217                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     218                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     219                    NULL, 0, /* Change this if we start sending host keys */
     220                    dh_client_pub, dh->pub_key, shared_secret,
     221                    &hash, &hashlen
     222                );
     223                break;
     224        case KEX_GSS_GEX_SHA1:
     225                kexgex_hash(
     226                    kex->evp_md,
     227                    kex->client_version_string, kex->server_version_string,
     228                    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
     229                    buffer_ptr(&kex->my), buffer_len(&kex->my),
     230                    NULL, 0,
     231                    min, nbits, max,
     232                    dh->p, dh->g,
     233                    dh_client_pub,
     234                    dh->pub_key,
     235                    shared_secret,
     236                    &hash, &hashlen
     237                );
     238                break;
     239        default:
     240                fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
     241        }
     242
     243        BN_clear_free(dh_client_pub);
     244
     245        if (kex->session_id == NULL) {
     246                kex->session_id_len = hashlen;
     247                kex->session_id = xmalloc(kex->session_id_len);
     248                memcpy(kex->session_id, hash, kex->session_id_len);
     249        }
     250
     251        gssbuf.value = hash;
     252        gssbuf.length = hashlen;
     253
     254        if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
     255                fatal("Couldn't get MIC");
     256
     257        packet_start(SSH2_MSG_KEXGSS_COMPLETE);
     258        packet_put_bignum2(dh->pub_key);
     259        packet_put_string(msg_tok.value,msg_tok.length);
     260
     261        if (send_tok.length != 0) {
     262                packet_put_char(1); /* true */
     263                packet_put_string(send_tok.value, send_tok.length);
     264        } else {
     265                packet_put_char(0); /* false */
     266        }
     267        packet_send();
     268
     269        gss_release_buffer(&min_status, &send_tok);
     270        gss_release_buffer(&min_status, &msg_tok);
     271
     272        if (gss_kex_context == NULL)
     273                gss_kex_context = ctxt;
     274        else
     275                ssh_gssapi_delete_ctx(&ctxt);
     276
     277        DH_free(dh);
     278
     279        kex_derive_keys(kex, hash, hashlen, shared_secret);
     280        BN_clear_free(shared_secret);
     281        kex_finish(kex);
     282
     283        /* If this was a rekey, then save out any delegated credentials we
     284         * just exchanged.  */
     285        if (options.gss_store_rekey)
     286                ssh_gssapi_rekey_creds();
     287}
     288#endif /* GSSAPI */
  • openssh-5.3p1

    old new key_type_from_name(char *name) 
    10201020                return KEY_RSA_CERT;
    10211021        } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
    10221022                return KEY_DSA_CERT;
     1023        } else if (strcmp(name, "null") == 0) {
     1024                return KEY_NULL;
    10231025        }
    10241026        debug2("key_type_from_name: unknown key type '%s'", name);
    10251027        return KEY_UNSPEC;
  • openssh-5.3p1

    old new enum types { 
    3939        KEY_DSA_CERT,
    4040        KEY_RSA_CERT_V00,
    4141        KEY_DSA_CERT_V00,
     42        KEY_NULL,
    4243        KEY_UNSPEC
    4344};
    4445enum fp_type {
  • openssh-5.3p1

    old new  
    172172int mm_answer_gss_accept_ctx(int, Buffer *);
    173173int mm_answer_gss_userok(int, Buffer *);
    174174int mm_answer_gss_checkmic(int, Buffer *);
     175int mm_answer_gss_sign(int, Buffer *);
     176int mm_answer_gss_updatecreds(int, Buffer *);
    175177#endif
    176178
    177179#ifdef SSH_AUDIT_EVENTS
     
    241243    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
    242244    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
    243245    {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
     246    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
    244247#endif
    245248#ifdef JPAKE
    246249    {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
     
    253256};
    254257
    255258struct mon_table mon_dispatch_postauth20[] = {
     259#ifdef GSSAPI
     260    {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx},
     261    {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
     262    {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
     263    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
     264#endif
    256265    {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
    257266    {MONITOR_REQ_SIGN, 0, mm_answer_sign},
    258267    {MONITOR_REQ_PTY, 0, mm_answer_pty},
     
    357366                /* Permit requests for moduli and signatures */
    358367                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
    359368                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
     369#ifdef GSSAPI
     370                /* and for the GSSAPI key exchange */
     371                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
     372#endif
    360373        } else {
    361374                mon_dispatch = mon_dispatch_proto15;
    362375
     
    443456                monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
    444457                monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
    445458                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
     459#ifdef GSSAPI
     460                /* and for the GSSAPI key exchange */
     461                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
     462#endif         
    446463        } else {
    447464                mon_dispatch = mon_dispatch_postauth15;
    448465                monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
     
    17061723        kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
    17071724        kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
    17081725        kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
     1726#ifdef GSSAPI
     1727        if (options.gss_keyex) {
     1728                kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
     1729                kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
     1730                kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
     1731        }
     1732#endif
    17091733        kex->server = 1;
    17101734        kex->hostkey_type = buffer_get_int(m);
    17111735        kex->kex_type = buffer_get_int(m);
     
    19111935        OM_uint32 major;
    19121936        u_int len;
    19131937
     1938        if (!options.gss_authentication && !options.gss_keyex)
     1939                fatal("In GSSAPI monitor when GSSAPI is disabled");
     1940
    19141941        goid.elements = buffer_get_string(m, &len);
    19151942        goid.length = len;
    19161943
     
    19381965        OM_uint32 flags = 0; /* GSI needs this */
    19391966        u_int len;
    19401967
     1968        if (!options.gss_authentication && !options.gss_keyex)
     1969                fatal("In GSSAPI monitor when GSSAPI is disabled");
     1970
    19411971        in.value = buffer_get_string(m, &len);
    19421972        in.length = len;
    19431973        major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
     
    19551985                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
    19561986                monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
    19571987                monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
     1988                monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
    19581989        }
    19591990        return (0);
    19601991}
     
    19661997        OM_uint32 ret;
    19671998        u_int len;
    19681999
     2000        if (!options.gss_authentication && !options.gss_keyex)
     2001                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2002
    19692003        gssbuf.value = buffer_get_string(m, &len);
    19702004        gssbuf.length = len;
    19712005        mic.value = buffer_get_string(m, &len);
     
    19922026{
    19932027        int authenticated;
    19942028
    1995         authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
     2029        if (!options.gss_authentication && !options.gss_keyex)
     2030                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2031
     2032        authenticated = authctxt->valid &&
     2033            ssh_gssapi_userok(authctxt->user, authctxt->pw);
    19962034
    19972035        buffer_clear(m);
    19982036        buffer_put_int(m, authenticated);
     
    20052043        /* Monitor loop will terminate if authenticated */
    20062044        return (authenticated);
    20072045}
     2046
     2047int
     2048mm_answer_gss_sign(int socket, Buffer *m)
     2049{
     2050        gss_buffer_desc data;
     2051        gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
     2052        OM_uint32 major, minor;
     2053        u_int len;
     2054
     2055        if (!options.gss_authentication && !options.gss_keyex)
     2056                fatal("In GSSAPI monitor when GSSAPI is disabled");
     2057
     2058        data.value = buffer_get_string(m, &len);
     2059        data.length = len;
     2060        if (data.length != 20)
     2061                fatal("%s: data length incorrect: %d", __func__,
     2062                    (int) data.length);
     2063
     2064        /* Save the session ID on the first time around */
     2065        if (session_id2_len == 0) {
     2066                session_id2_len = data.length;
     2067                session_id2 = xmalloc(session_id2_len);
     2068                memcpy(session_id2, data.value, session_id2_len);
     2069        }
     2070        major = ssh_gssapi_sign(gsscontext, &data, &hash);
     2071
     2072        xfree(data.value);
     2073
     2074        buffer_clear(m);
     2075        buffer_put_int(m, major);
     2076        buffer_put_string(m, hash.value, hash.length);
     2077
     2078        mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
     2079
     2080        gss_release_buffer(&minor, &hash);
     2081
     2082        /* Turn on getpwnam permissions */
     2083        monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
     2084       
     2085        /* And credential updating, for when rekeying */
     2086        monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
     2087
     2088        return (0);
     2089}
     2090
     2091int
     2092mm_answer_gss_updatecreds(int socket, Buffer *m) {
     2093        ssh_gssapi_ccache store;
     2094        int ok;
     2095
     2096        store.filename = buffer_get_string(m, NULL);
     2097        store.envvar   = buffer_get_string(m, NULL);
     2098        store.envval   = buffer_get_string(m, NULL);
     2099
     2100        ok = ssh_gssapi_update_creds(&store);
     2101
     2102        xfree(store.filename);
     2103        xfree(store.envvar);
     2104        xfree(store.envval);
     2105
     2106        buffer_clear(m);
     2107        buffer_put_int(m, ok);
     2108
     2109        mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
     2110
     2111        return(0);
     2112}
     2113
    20082114#endif /* GSSAPI */
    20092115
    20102116#ifdef JPAKE
  • openssh-5.3p1

    old new  
    5353        MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
    5454        MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
    5555        MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
     56        MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
     57        MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
    5658        MONITOR_REQ_PAM_START,
    5759        MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
    5860        MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
  • monitor_wrap.c

    old new  
    12481248}
    12491249
    12501250int
    1251 mm_ssh_gssapi_userok(char *user)
     1251mm_ssh_gssapi_userok(char *user, struct passwd *pw)
    12521252{
    12531253        Buffer m;
    12541254        int authenticated = 0;
     
    12651265        debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
    12661266        return (authenticated);
    12671267}
     1268
     1269OM_uint32
     1270mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
     1271{
     1272        Buffer m;
     1273        OM_uint32 major;
     1274        u_int len;
     1275
     1276        buffer_init(&m);
     1277        buffer_put_string(&m, data->value, data->length);
     1278
     1279        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
     1280        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
     1281
     1282        major = buffer_get_int(&m);
     1283        hash->value = buffer_get_string(&m, &len);
     1284        hash->length = len;
     1285
     1286        buffer_free(&m);
     1287
     1288        return(major);
     1289}
     1290
     1291int
     1292mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
     1293{
     1294        Buffer m;
     1295        int ok;
     1296
     1297        buffer_init(&m);
     1298
     1299        buffer_put_cstring(&m, store->filename ? store->filename : "");
     1300        buffer_put_cstring(&m, store->envvar ? store->envvar : "");
     1301        buffer_put_cstring(&m, store->envval ? store->envval : "");
     1302       
     1303        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
     1304        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
     1305
     1306        ok = buffer_get_int(&m);
     1307
     1308        buffer_free(&m);
     1309       
     1310        return (ok);
     1311}
     1312
    12681313#endif /* GSSAPI */
    12691314
    12701315#ifdef JPAKE
  • monitor_wrap.h

    old new  
    5757OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
    5858OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    5959   gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
    60 int mm_ssh_gssapi_userok(char *user);
     60int mm_ssh_gssapi_userok(char *user, struct passwd *);
    6161OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
     62OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
     63int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
    6264#endif
    6365
    6466#ifdef USE_PAM
  • openssh-5.3p1

    old new  
    11/* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
    22/*
    3  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
     3 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
    66 * modification, are permitted provided that the following conditions
     
    6060
    6161#define SSH_GSS_OIDTYPE 0x06
    6262
     63#define SSH2_MSG_KEXGSS_INIT                            30
     64#define SSH2_MSG_KEXGSS_CONTINUE                        31
     65#define SSH2_MSG_KEXGSS_COMPLETE                        32
     66#define SSH2_MSG_KEXGSS_HOSTKEY                         33
     67#define SSH2_MSG_KEXGSS_ERROR                           34
     68#define SSH2_MSG_KEXGSS_GROUPREQ                        40
     69#define SSH2_MSG_KEXGSS_GROUP                           41
     70#define KEX_GSS_GRP1_SHA1_ID                            "gss-group1-sha1-"
     71#define KEX_GSS_GRP14_SHA1_ID                           "gss-group14-sha1-"
     72#define KEX_GSS_GEX_SHA1_ID                             "gss-gex-sha1-"
     73
    6374typedef struct {
    6475        char *filename;
    6576        char *envvar;
    6677        char *envval;
     78        struct passwd *owner;
    6779        void *data;
    6880} ssh_gssapi_ccache;
    6981
     
    7183        gss_buffer_desc displayname;
    7284        gss_buffer_desc exportedname;
    7385        gss_cred_id_t creds;
     86        gss_name_t name;
    7487        struct ssh_gssapi_mech_struct *mech;
    7588        ssh_gssapi_ccache store;
     89        int used;
     90        int updated;
    7691} ssh_gssapi_client;
    7792
    7893typedef struct ssh_gssapi_mech_struct {
     
    8398        int (*userok) (ssh_gssapi_client *, char *);
    8499        int (*localname) (ssh_gssapi_client *, char **);
    85100        void (*storecreds) (ssh_gssapi_client *);
     101        int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
    86102} ssh_gssapi_mech;
    87103
    88104typedef struct {
     
    93109        gss_OID         oid; /* client */
    94110        gss_cred_id_t   creds; /* server */
    95111        gss_name_t      client; /* server */
    96         gss_cred_id_t   client_creds; /* server */
     112        gss_cred_id_t   client_creds; /* both */
    97113} Gssctxt;
    98114
    99115extern ssh_gssapi_mech *supported_mechs[];
     116extern Gssctxt *gss_kex_context;
    100117
    101118int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
    102119void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
     
    116133void ssh_gssapi_delete_ctx(Gssctxt **);
    117134OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
    118135void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
    119 int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
     136int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
     137OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
     138int ssh_gssapi_credentials_updated(Gssctxt *);
    120139
    121140/* In the server */
     141typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
     142    const char *);
     143char *ssh_gssapi_client_mechanisms(const char *, const char *);
     144char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
     145    const char *);
     146gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
     147int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
     148    const char *);
    122149OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
    123 int ssh_gssapi_userok(char *name);
     150int ssh_gssapi_userok(char *name, struct passwd *);
    124151OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
    125152void ssh_gssapi_do_child(char ***, u_int *);
    126153void ssh_gssapi_cleanup_creds(void);
    127154void ssh_gssapi_storecreds(void);
    128155
     156char *ssh_gssapi_server_mechanisms(void);
     157int ssh_gssapi_oid_table_ok();
     158
     159int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
    129160#endif /* GSSAPI */
    130161
    131162#endif /* _SSH_GSS_H */
  • openssh-5.3p1

    old new  
    2626#   HostbasedAuthentication no
    2727#   GSSAPIAuthentication no
    2828#   GSSAPIDelegateCredentials no
     29#   GSSAPIKeyExchange no
     30#   GSSAPITrustDNS no
    2931#   BatchMode no
    3032#   CheckHostIP yes
    3133#   AddressFamily any
  • clientloop.c

    old new  
    111111#include "msg.h"
    112112#include "roaming.h"
    113113
     114#ifdef GSSAPI
     115#include "ssh-gss.h"
     116#endif
     117
    114118/* import options */
    115119extern Options options;
    116120
     
    14301434                /* Do channel operations unless rekeying in progress. */
    14311435                if (!rekeying) {
    14321436                        channel_after_select(readset, writeset);
     1437
     1438#ifdef GSSAPI
     1439                        if (options.gss_renewal_rekey &&
     1440                            ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) {
     1441                                debug("credentials updated - forcing rekey");
     1442                                need_rekeying = 1;
     1443                        }
     1444#endif
     1445
    14331446                        if (need_rekeying || packet_need_rekeying()) {
    14341447                                debug("need rekeying");
    14351448                                xxx_kex->done = 0;