}
#ifdef GSI
-int get_gssapi_cred()
+int get_gsi_cred()
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
-
-
+ gss_OID_set oidset;
+
debug("calling gss_acquire_cred");
+ gss_create_empty_oid_set(&min_stat,&oidset);
+ gss_add_oid_set_member(&min_stat,&supported_mechs[GSI].oid,&oidset);
maj_stat = gss_acquire_cred(&min_stat,
GSS_C_NO_NAME,
GSS_C_INDEFINITE,
- GSS_C_NO_OID_SET,
+ oidset,
GSS_C_INITIATE,
&gss_cred,
NULL,
return 1; /* Success */
}
-char * get_gss_our_name()
+char * get_gsi_name()
{
OM_uint32 maj_stat;
OM_uint32 min_stat;
gss_ctx_id_t gss_context;
gss_OID_desc mech_oid;
gss_OID name_type;
- gss_OID_set my_mechs;
- int my_mech_num;
+ gss_OID_set gss_mechs, my_mechs;
+ int my_mech_num, i, present;
OM_uint32 maj_stat;
OM_uint32 min_stat;
int ret_stat = 0; /* 1 == success */
OM_uint32 req_flags = 0;
OM_uint32 ret_flags;
int type;
- char *gssapi_auth_type = NULL;
char *xhost;
unsigned int slen;
+ Gssctxt *ctx = NULL;
/* Make a copy of the host name, in case it was returned by a
* previous call to gethostbyname(). */
/* Do mutual authentication */
req_flags |= GSS_C_MUTUAL_FLAG;
-#ifdef KRB5
-
- gssapi_auth_type = "GSSAPI/Kerberos 5";
-
-#endif
-
-#ifdef GSI
-
- gssapi_auth_type = "GSSAPI/GLOBUS";
-
-#endif /* GSI */
-
- if (gssapi_auth_type == NULL) {
- debug("No GSSAPI type defined during compile");
- goto cleanup;
- }
-
- debug("Attempting %s authentication", gssapi_auth_type);
-
service_name = (char *) xmalloc(strlen("host") +
strlen(xhost) +
2 /* 1 for '@', 1 for NUL */);
/* Forward credentials? */
-#ifdef KRB5
- if (options->kerberos_tgt_passing) {
- debug("Forwarding Kerberos credentials");
- req_flags |= GSS_C_DELEG_FLAG;
- }
-#endif /* KRB5 */
-
#ifdef GSSAPI
if(options->gss_deleg_creds) {
- debug("Forwarding X509 proxy certificate");
+ debug("Delegating GSSAPI credentials");
req_flags |= GSS_C_DELEG_FLAG;
}
-#ifdef GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG
- /* Forward limited credentials, overrides gss_deleg_creds */
- if(options->gss_globus_deleg_limited_proxy) {
- debug("Forwarding limited X509 proxy certificate");
- req_flags |= (GSS_C_DELEG_FLAG | GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG);
- }
-#endif /* GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG */
-
#endif /* GSSAPI */
debug("req_flags = %u", (unsigned int)req_flags);
goto cleanup;
}
- maj_stat = gss_indicate_mechs(&min_stat, &my_mechs);
+ maj_stat = gss_indicate_mechs(&min_stat, &gss_mechs);
if (maj_stat != GSS_S_COMPLETE) {
display_gssapi_status("indicating mechs", maj_stat, min_stat);
goto cleanup;
}
+ /* The GSSAPI supports the mechs in gss_mechs, but which ones do
+ we have credentials for? We only get one try, so we don't want
+ to propose a mechanism we know is going to fail. */
+ maj_stat = gss_create_empty_oid_set(&min_stat, &my_mechs);
+ for (i=0; supported_mechs[i].name != NULL; i++) {
+ maj_stat = gss_test_oid_set_member(&min_stat, &supported_mechs[i].oid,
+ gss_mechs, &present);
+ if (present) {
+ if (!GSS_ERROR(ssh_gssapi_client_ctx(&ctx, &supported_mechs[i].oid,
+ host))) {
+ maj_stat = gss_add_oid_set_member(&min_stat,
+ &supported_mechs[i].oid,
+ &my_mechs);
+ debug("GSSAPI mechanism %s supported", supported_mechs[i].name);
+ } else {
+ debug("no credentials for GSSAPI mechanism %s",
+ supported_mechs[i].name);
+ }
+ } else {
+ debug("GSSAPI mechanism %s not supported", supported_mechs[i].name);
+ }
+ }
+
/*
* Send over a packet to the daemon, letting it know we're doing
* GSSAPI and our mech_oid(s).
*/
- debug("Sending mech oid to server");
+ debug("Sending mech oid(s) to server");
packet_start(SSH_CMSG_AUTH_GSSAPI);
packet_put_int(my_mechs->count); /* Number of mechs we're sending */
- for (my_mech_num = 0; my_mech_num < my_mechs->count; my_mech_num++)
+#ifdef GSI
+ /* Send GSI before Kerberos, because if GSI fails, we can always fall
+ back and try regular Kerberos authentication with our Kerberos cred. */
+ maj_stat = gss_test_oid_set_member(&min_stat, &supported_mechs[GSI].oid,
+ my_mechs, &present);
+ if (present) {
+ packet_put_string(supported_mechs[GSI].oid.elements,
+ supported_mechs[GSI].oid.length);
+ }
+#endif
+ for (my_mech_num = 0; my_mech_num < my_mechs->count; my_mech_num++) {
+#ifdef GSI
+ /* Skip GSI. We already sent it above. */
+ if ((my_mechs->elements[my_mech_num].length ==
+ supported_mechs[GSI].oid.length) &&
+ memcmp(my_mechs->elements[my_mech_num].elements,
+ supported_mechs[GSI].oid.elements,
+ my_mechs->elements[my_mech_num].length) == 0) {
+ continue;
+ }
+#endif
packet_put_string(my_mechs->elements[my_mech_num].elements,
my_mechs->elements[my_mech_num].length);
+ }
packet_send();
packet_write_wait();
/* Success */
ret_stat = 1;
- debug("%s authentication successful", gssapi_auth_type);
+ debug("GSSAPI authentication successful");
/*
* Read hash of host and server keys and make sure it
*/
if ((supported_authentications & (1 << SSH_AUTH_GSSAPI)) &&
options.gss_authentication) {
- if (get_gssapi_cred()) {
+ if (get_gsi_cred()) {
char * retname;
char * newname;
save_server_user = server_user;
- retname = get_gss_our_name();
+ retname = get_gsi_name();
if (retname) {
debug("passing gssapi name '%s'", retname);
}
}
}
- } else {
- /*
- * If we couldn't successfully get our GSSAPI credentials then
- * turn off gssapi authentication
- */
- options.gss_authentication = 0;
}
debug("server_user %s", server_user);
}