int main(int argc, char **argv) { OM_uint32 minor_status, maj_stat; gss_buffer_desc data; int ret; maj_stat = gss_oid_to_str(&minor_status, GSS_KRB5_MECHANISM, &data); if (GSS_ERROR(maj_stat)) errx(1, "gss_oid_to_str failed"); ret = strncmp(data.value, "1 2 840 113554 1 2 2", data.length); gss_release_buffer(&maj_stat, &data); if (ret) return 1; maj_stat = gss_oid_to_str(&minor_status, GSS_C_NT_EXPORT_NAME, &data); if (GSS_ERROR(maj_stat)) errx(1, "gss_oid_to_str failed"); ret = strncmp(data.value, "1 3 6 1 5 6 4", data.length); gss_release_buffer(&maj_stat, &data); if (ret) return 1; return 0; }
static void gt_gss_error(char *name, gss_OID mech, uint32_t maj, uint32_t min) { AUTOCLEAN(struct gss_err err, autofreegsserr) = { {0}, 0, 0}; OM_uint32 msgctx; fprintf(stderr, "[%s] Failed with:", name); if (mech != GSS_C_NO_OID) { err.maj = gss_oid_to_str(&err.min, mech, &err.buf); if (err.maj != GSS_S_COMPLETE) return; fprintf(stderr, " (OID: %s)", (char *)err.buf.value); (void)gss_release_buffer(&err.min, &err.buf); } msgctx = 0; err.maj = gss_display_status(&err.min, maj, GSS_C_GSS_CODE, mech, &msgctx, &err.buf); if (err.maj != GSS_S_COMPLETE) return; fprintf(stderr, " %s,", (char *)err.buf.value); (void)gss_release_buffer(&err.min, &err.buf); msgctx = 0; err.maj = gss_display_status(&err.min, min, GSS_C_MECH_CODE, mech, &msgctx, &err.buf); if (err.maj != GSS_S_COMPLETE) return; fprintf(stderr, " %s\n", (char *)err.buf.value); (void)gss_release_buffer(&err.min, &err.buf); }
void gp_fmt_status(gss_OID mech, uint32_t maj, uint32_t min, char *buf, size_t buf_size) { uint32_t msgctx; uint32_t discard; gss_buffer_desc tmp; size_t used = 0; if (mech != GSS_C_NO_OID) { gss_oid_to_str(&discard, mech, &tmp); used += gp_append(buf + used, buf_size - used, "(OID: %s) ", (char *)tmp.value); gss_release_buffer(&discard, &tmp); } msgctx = 0; gss_display_status(&discard, maj, GSS_C_GSS_CODE, mech, &msgctx, &tmp); used += gp_append(buf + used, buf_size - used, "%s, ", (char *)tmp.value); gss_release_buffer(&discard, &tmp); msgctx = 0; gss_display_status(&discard, min, GSS_C_MECH_CODE, mech, &msgctx, &tmp); used += gp_append(buf + used, buf_size - used, "%s", (char *)tmp.value); gss_release_buffer(&discard, &tmp); }
int supported_mechanisms(void *argptr, int argc, char **argv) { OM_uint32 maj_stat, min_stat; gss_OID_set mechs; rtbl_t ct; size_t i; maj_stat = gss_indicate_mechs(&min_stat, &mechs); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_indicate_mechs failed"); printf("Supported mechanisms:\n"); ct = rtbl_create(); if (ct == NULL) errx(1, "rtbl_create"); rtbl_set_separator(ct, " "); rtbl_add_column(ct, COL_OID, 0); rtbl_add_column(ct, COL_NAME, 0); rtbl_add_column(ct, COL_DESC, 0); rtbl_add_column(ct, COL_SASL, 0); for (i = 0; i < mechs->count; i++) { gss_buffer_desc str, sasl_name, mech_name, mech_desc; maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &str); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_oid_to_str failed"); rtbl_add_column_entryv(ct, COL_OID, "%.*s", (int)str.length, (char *)str.value); gss_release_buffer(&min_stat, &str); (void)gss_inquire_saslname_for_mech(&min_stat, &mechs->elements[i], &sasl_name, &mech_name, &mech_desc); rtbl_add_column_entryv(ct, COL_NAME, "%.*s", (int)mech_name.length, (char *)mech_name.value); rtbl_add_column_entryv(ct, COL_DESC, "%.*s", (int)mech_desc.length, (char *)mech_desc.value); rtbl_add_column_entryv(ct, COL_SASL, "%.*s", (int)sasl_name.length, (char *)sasl_name.value); gss_release_buffer(&min_stat, &mech_name); gss_release_buffer(&min_stat, &mech_desc); gss_release_buffer(&min_stat, &sasl_name); } gss_release_oid_set(&min_stat, &mechs); rtbl_format(ct, stdout); rtbl_destroy(ct); return 0; }
void display_oid(const char *tag, gss_OID oid) { OM_uint32 major, minor; gss_buffer_desc buf; major = gss_oid_to_str(&minor, oid, &buf); check_gsserr("gss_oid_to_str", major, minor); if (tag != NULL) printf("%s:\t", tag); printf("%.*s\n", (int)buf.length, (char *)buf.value); (void)gss_release_buffer(&minor, &buf); }
int supported_mechanisms(void *argptr, int argc, char **argv) { OM_uint32 maj_stat, min_stat; gss_OID_set mechs; rtbl_t ct; size_t i; maj_stat = gss_indicate_mechs(&min_stat, &mechs); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_indicate_mechs failed"); printf("Supported mechanisms:\n"); ct = rtbl_create(); if (ct == NULL) errx(1, "rtbl_create"); rtbl_set_separator(ct, " "); rtbl_add_column(ct, COL_OID, 0); rtbl_add_column(ct, COL_NAME, 0); for (i = 0; i < mechs->count; i++) { gss_buffer_desc name; maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &name); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_oid_to_str failed"); rtbl_add_column_entryv(ct, COL_OID, "%.*s", (int)name.length, (char *)name.value); gss_release_buffer(&min_stat, &name); if (gss_oid_equal(&mechs->elements[i], GSS_KRB5_MECHANISM)) rtbl_add_column_entry(ct, COL_NAME, "Kerberos 5"); else if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) rtbl_add_column_entry(ct, COL_NAME, "SPNEGO"); else if (gss_oid_equal(&mechs->elements[i], GSS_NTLM_MECHANISM)) rtbl_add_column_entry(ct, COL_NAME, "NTLM"); } gss_release_oid_set(&min_stat, &mechs); rtbl_format(ct, stdout); rtbl_destroy(ct); return 0; }
static OM_uint32 displayOID(OM_uint32 *minor, gss_OID oid, char *tag) { OM_uint32 major, tmp_minor; gss_buffer_desc buf; major = gss_oid_to_str(minor, oid, &buf); if (GSS_ERROR(major)) { displayStatus("gss_oid_to_str", major, *minor); return major; } printf("%s:\t%s\n", tag, (char *)buf.value); gss_release_buffer(&tmp_minor, &buf); return GSS_S_COMPLETE; }
int main(int argc,char *argv[]) { char strbuf[BUFSIZE]; OM_uint32 oidvec[MAXOID]; OM_uint32 oidvecsize; unsigned char enc_oid_buf[BUFSIZE]; gss_OID oid = NULL; gss_buffer_desc buf; OM_uint32 stat, minor; while (fgets(strbuf,BUFSIZE,stdin)!=NULL) { if ((strbuf[0]!='#') && (strlen(strbuf) > 1)) { buf.length = strlen(strbuf) - 1; buf.value = (void *) strbuf; stat = gss_str_to_oid (&minor, &buf, &oid); printf ("gss_str_to_oid returns %u, %u\n", stat, minor); print_oid (oid); stat = gss_oid_to_str (&minor, oid, &buf); printf ("gss_oid_to_str returns %u, %u\n", stat, minor); printf ("string form of OID is \"%*.*s\"\n", buf.length, buf.length, buf.value); ilugss_free (oid); } } }
int main(int argc, char **argv) { const char *name = "*****@*****.**"; OM_uint32 major, minor; gss_name_t gss_name; gss_buffer_desc buf; gss_OID name_oid; gss_name = import_name(name); major = gss_display_name(&minor, gss_name, &buf, &name_oid); check_gsserr("gss_display_name", major, minor); printf("name is: %.*s\n", (int)buf.length, (char *)buf.value); (void)gss_release_buffer(&minor, &buf); major = gss_oid_to_str(&minor, name_oid, &buf); check_gsserr("gss_oid_to_str", major, minor); printf("name type is: %.*s\n", (int)buf.length, (char *)buf.value); (void)gss_release_buffer(&minor, &buf); (void)gss_release_name(&minor, &gss_name); return 0; }
static bool_t Svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr) { struct svc_rpc_gss_data *gd; struct rpc_gss_cred *gc; gss_buffer_desc recv_tok, seqbuf; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); gc = (struct rpc_gss_cred *)rqst->rq_clntcred; memset(gr, 0, sizeof(*gr)); /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); if(!svc_getargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok)) return (FALSE); gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, &mech, &gr->gr_token, &ret_flags, NULL, NULL); svc_freeargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok); if(gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED) { sockaddr_t addr; char ipstring[SOCK_NAME_MAX]; copy_xprt_addr(&addr, rqst->rq_xprt); sprint_sockaddr(&addr, ipstring, sizeof(ipstring)); LogWarn(COMPONENT_RPCSEC_GSS, "Bad authentication major=%u minor=%u addr=%s", gr->gr_major, gr->gr_minor, ipstring); gd->ctx = GSS_C_NO_CONTEXT; goto errout; } /* * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, * one to the mechanism oid, one to the internal_ctx_id */ if((gr->gr_ctx.value = Mem_Alloc(sizeof(gss_union_ctx_id_desc))) == NULL) { LogCrit(COMPONENT_RPCSEC_GSS, "svcauth_gss_accept_context: out of memory"); goto errout; } memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); /* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version... */ gr->gr_win = sizeof(gd->seqmask) * 8; /* Save client info. */ gd->sec.mech = mech; gd->sec.qop = GSS_C_QOP_DEFAULT; gd->sec.svc = gc->gc_svc; gd->seq = gc->gc_seq; gd->win = gr->gr_win; if(gr->gr_major == GSS_S_COMPLETE) { #ifdef SPKM /* spkm3: no src_name (anonymous) */ if(!g_OID_equal(gss_mech_spkm3, mech)) { #endif maj_stat = gss_display_name(&min_stat, gd->client_name, &gd->cname, &gd->sec.mech); LogFullDebug(COMPONENT_RPCSEC_GSS, "cname.val: %s cname.len: %d", (char *)gd->cname.value, (int)gd->cname.length); #ifdef SPKM } #endif if(maj_stat != GSS_S_COMPLETE) { } #ifdef HAVE_HEIMDAL #else if(isFullDebug(COMPONENT_RPCSEC_GSS)) { gss_buffer_desc mechname; gss_oid_to_str(&min_stat, mech, &mechname); gss_release_buffer(&min_stat, &mechname); } #endif seq = htonl(gr->gr_win); seqbuf.value = &seq; seqbuf.length = sizeof(seq); gss_release_buffer(&min_stat, &gd->checksum); LogFullDebug(COMPONENT_RPCSEC_GSS, "gss_sign in sec_accept_context"); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &gd->checksum); if(maj_stat != GSS_S_COMPLETE) { goto errout; } rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value; rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length; } return (TRUE); errout: gss_release_buffer(&min_stat, &gr->gr_token); return (FALSE); }
static bool svcauth_gss_accept_sec_context(struct svc_req *req, struct svc_rpc_gss_data *gd, struct rpc_gss_init_res *gr) { struct rpc_gss_cred *gc; gss_buffer_desc recv_tok, seqbuf, checksum; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; #define INDEF_EXPIRE 60*60*24 /* from mit k5 src/lib/rpc/svc_auth_gssapi.c */ OM_uint32 time_rec; gc = (struct rpc_gss_cred *)req->rq_clntcred; memset(gr, 0, sizeof(*gr)); /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); if (!svc_getargs (req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args, (caddr_t) &recv_tok, NULL /* u_data */)) return (false); gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, &mech, &gr->gr_token, &ret_flags, &time_rec, NULL); svc_freeargs(req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args, (caddr_t) &recv_tok); if ((gr->gr_major != GSS_S_COMPLETE) && (gr->gr_major != GSS_S_CONTINUE_NEEDED)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: auth failed major=%u minor=%u", __func__, gr->gr_major, gr->gr_minor); gd->ctx = GSS_C_NO_CONTEXT; gss_release_buffer(&min_stat, &gr->gr_token); return (false); } /* ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, * one to the mechanism oid, one to the internal_ctx_id */ gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc)); memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); /* ANDROS: change for debugging linux kernel version... gr->gr_win = 0x00000005; */ gr->gr_win = sizeof(gd->seqmask) * 8; /* Save client info. */ gd->sec.mech = mech; gd->sec.qop = GSS_C_QOP_DEFAULT; gd->sec.svc = gc->gc_svc; gd->win = gr->gr_win; if (time_rec == GSS_C_INDEFINITE) time_rec = INDEF_EXPIRE; if (time_rec > 10) time_rec -= 5; gd->endtime = time_rec + get_time_fast(); if (gr->gr_major == GSS_S_COMPLETE) { maj_stat = gss_display_name(&min_stat, gd->client_name, &gd->cname, &gd->sec.mech); if (maj_stat != GSS_S_COMPLETE) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: display_name major=%u minor=%u", __func__, maj_stat, min_stat); gss_release_buffer(&min_stat, &gr->gr_token); return (false); } #ifdef DEBUG #ifdef HAVE_KRB5 { gss_buffer_desc mechname; gss_oid_to_str(&min_stat, mech, &mechname); __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: accepted context for %.*s with " "<mech %.*s, qop %d, svc %d>", __func__, gd->cname.length, (char *)gd->cname.value, mechname.length, (char *)mechname.value, gd->sec.qop, gd->sec.svc); gss_release_buffer(&min_stat, &mechname); } #elif HAVE_HEIMDAL __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: accepted context for %.*s with " "<mech {}, qop %d, svc %d>", __func__, gd->cname.length, (char *)gd->cname.value, gd->sec.qop, gd->sec.svc); #endif #endif /* DEBUG */ seq = htonl(gr->gr_win); seqbuf.value = &seq; seqbuf.length = sizeof(seq); gss_release_buffer(&min_stat, &gd->checksum); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) { gss_release_buffer(&min_stat, &gr->gr_token); return (false); } /* XXX ref? (assert gd->locked?) */ req->rq_verf.oa_flavor = RPCSEC_GSS; req->rq_verf.oa_base = checksum.value; req->rq_verf.oa_length = checksum.length; } return (true); }
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_status(OM_uint32 *minor_status, OM_uint32 status_value, int status_type, const gss_OID mech_type, OM_uint32 *message_content, gss_buffer_t status_string) { OM_uint32 major_status; _mg_buffer_zero(status_string); *message_content = 0; major_status = _gss_mg_get_error(mech_type, status_type, status_value, status_string); if (major_status == GSS_S_COMPLETE) { *message_content = 0; *minor_status = 0; return GSS_S_COMPLETE; } *minor_status = 0; switch (status_type) { case GSS_C_GSS_CODE: { char *buf = NULL; int e; if (GSS_SUPPLEMENTARY_INFO(status_value)) e = asprintf(&buf, "%s", supplementary_error( GSS_SUPPLEMENTARY_INFO(status_value))); else e = asprintf (&buf, "%s %s", calling_error(GSS_CALLING_ERROR(status_value)), routine_error(GSS_ROUTINE_ERROR(status_value))); if (e < 0 || buf == NULL) break; status_string->length = strlen(buf); status_string->value = buf; return GSS_S_COMPLETE; } case GSS_C_MECH_CODE: { OM_uint32 maj_junk, min_junk; gss_buffer_desc oid; char *buf = NULL; int e; maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid); if (maj_junk != GSS_S_COMPLETE) { oid.value = rk_UNCONST("unknown"); oid.length = 7; } e = asprintf (&buf, "unknown mech-code %lu for mech %.*s", (unsigned long)status_value, (int)oid.length, (char *)oid.value); if (maj_junk == GSS_S_COMPLETE) gss_release_buffer(&min_junk, &oid); if (e < 0 || buf == NULL) break; status_string->length = strlen(buf); status_string->value = buf; return GSS_S_COMPLETE; } } _mg_buffer_zero(status_string); return (GSS_S_BAD_STATUS); }
static bool_t svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr) { struct svc_rpc_gss_data *gd; struct rpc_gss_cred *gc; gss_buffer_desc recv_tok, seqbuf, checksum; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; log_debug("in svcauth_gss_accept_context()"); gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); gc = (struct rpc_gss_cred *)rqst->rq_clntcred; memset(gr, 0, sizeof(*gr)); /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); if (!svc_getargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t)&recv_tok)) return (FALSE); gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, _svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, &mech, &gr->gr_token, &ret_flags, NULL, NULL); if (gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED) { log_status("accept_sec_context", gr->gr_major, gr->gr_minor); gd->ctx = GSS_C_NO_CONTEXT; gss_release_buffer(&min_stat, &gr->gr_token); return (FALSE); } /* ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, * one to the mechanism oid, one to the internal_ctx_id */ if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) { fprintf(stderr, "svcauth_gss_accept_context: out of memory\n"); return (FALSE); } memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); /* ANDROS: change for debugging linux kernel version... gr->gr_win = sizeof(gd->seqmask) * 8; */ gr->gr_win = 0x00000005; /* Save client info. */ gd->sec.mech = mech; gd->sec.qop = GSS_C_QOP_DEFAULT; gd->sec.svc = gc->gc_svc; gd->seq = gc->gc_seq; gd->win = gr->gr_win; if (gr->gr_major == GSS_S_COMPLETE) { maj_stat = gss_display_name(&min_stat, gd->client_name, &gd->cname, &gd->sec.mech); if (maj_stat != GSS_S_COMPLETE) { log_status("display_name", maj_stat, min_stat); return (FALSE); } #ifdef DEBUG #ifdef HAVE_KRB5 { gss_buffer_desc mechname; gss_oid_to_str(&min_stat, mech, &mechname); log_debug("accepted context for %.*s with " "<mech %.*s, qop %d, svc %d>", gd->cname.length, (char *)gd->cname.value, mechname.length, (char *)mechname.value, gd->sec.qop, gd->sec.svc); gss_release_buffer(&min_stat, &mechname); } #elif HAVE_HEIMDAL log_debug("accepted context for %.*s with " "<mech {}, qop %d, svc %d>", gd->cname.length, (char *)gd->cname.value, gd->sec.qop, gd->sec.svc); #endif #endif /* DEBUG */ seq = htonl(gr->gr_win); seqbuf.value = &seq; seqbuf.length = sizeof(seq); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) return (FALSE); rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; rqst->rq_xprt->xp_verf.oa_base = checksum.value; rqst->rq_xprt->xp_verf.oa_length = checksum.length; } return (TRUE); }
int nfs_rpc_req2client_cred(struct svc_req *reqp, nfs_client_cred_t * pcred) { /* Structure for managing basic AUTH_UNIX authentication */ struct authunix_parms *aup = NULL; /* Stuff needed for managing RPCSEC_GSS */ #ifdef _HAVE_GSSAPI OM_uint32 maj_stat = 0; OM_uint32 min_stat = 0; struct svc_rpc_gss_data *gd = NULL; gss_buffer_desc oidbuff; #endif if(reqp == NULL || pcred == NULL) return -1; pcred->flavor = reqp->rq_cred.oa_flavor; pcred->length = reqp->rq_cred.oa_length; switch (reqp->rq_cred.oa_flavor) { case AUTH_NONE: /* Do nothing... because there seems like nothing is to be done... */ break; case AUTH_UNIX: aup = (struct authunix_parms *)(reqp->rq_clntcred); pcred->auth_union.auth_unix.aup_uid = aup->aup_uid; pcred->auth_union.auth_unix.aup_gid = aup->aup_gid; pcred->auth_union.auth_unix.aup_time = aup->aup_time; break; #ifdef _HAVE_GSSAPI case RPCSEC_GSS: /* Extract the information from the RPCSEC_GSS opaque structure */ gd = SVCAUTH_PRIVATE(reqp->rq_xprt->xp_auth); pcred->auth_union.auth_gss.svc = (unsigned int)(gd->sec.svc); pcred->auth_union.auth_gss.qop = (unsigned int)(gd->sec.qop); pcred->auth_union.auth_gss.gss_context_id = gd->ctx; strncpy(pcred->auth_union.auth_gss.cname, gd->cname.value, NFS_CLIENT_NAME_LEN); if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE) { char errbuff[1024]; log_sperror_gss(errbuff, maj_stat, min_stat); LogCrit(COMPONENT_DISPATCH, "GSSAPI ERROR: %u|%u = %s", maj_stat, min_stat, errbuff); return -1; } strncpy(pcred->auth_union.auth_gss.stroid, oidbuff.value, NFS_CLIENT_NAME_LEN); /* Je fais le menage derriere moi */ (void)gss_release_buffer(&min_stat, &oidbuff); break; #endif default: /* Unsupported authentication flavour */ return -1; break; } return 1; } /* nfs_rpc_req2client_cred */
/** * * get_req_uid_gid: * * * * @param ptr_req [IN] incoming request. * @param pexport_client [IN] related export client * @param pexport [IN] related export entry * @param user_credentials [OUT] Filled in structure with uid and gids * * @return TRUE if successful, FALSE otherwise * */ int get_req_uid_gid(struct svc_req *ptr_req, exportlist_client_entry_t * pexport_client, exportlist_t * pexport, struct user_cred *user_credentials) { struct authunix_parms *punix_creds = NULL; unsigned int rpcxid = 0; #ifdef _HAVE_GSSAPI struct svc_rpc_gss_data *gd = NULL; char principal[MAXNAMLEN]; #endif if (user_credentials == NULL) return FALSE; rpcxid = get_rpc_xid(ptr_req); switch (ptr_req->rq_cred.oa_flavor) { case AUTH_NONE: /* Nothing to be done here... */ LogFullDebug(COMPONENT_DISPATCH, "Request xid=%u has authentication AUTH_NONE", rpcxid); break; case AUTH_UNIX: LogFullDebug(COMPONENT_DISPATCH, "Request xid=%u has authentication AUTH_UNIX", rpcxid); /* We map the rq_cred to Authunix_parms */ punix_creds = (struct authunix_parms *)ptr_req->rq_clntcred; /* Get the uid/gid couple */ user_credentials->caller_uid = punix_creds->aup_uid; user_credentials->caller_gid = punix_creds->aup_gid; user_credentials->caller_glen = punix_creds->aup_len; user_credentials->caller_garray = punix_creds->aup_gids; LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u", (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid); break; #ifdef _HAVE_GSSAPI case RPCSEC_GSS: LogFullDebug(COMPONENT_DISPATCH, "Request xid=%u has authentication RPCSEC_GSS", rpcxid); /* Get the gss data to process them */ gd = SVCAUTH_PRIVATE(ptr_req->rq_xprt->xp_auth); if(isFullDebug(COMPONENT_RPCSEC_GSS)) { OM_uint32 maj_stat = 0; OM_uint32 min_stat = 0; char ptr[256]; gss_buffer_desc oidbuff; LogFullDebug(COMPONENT_RPCSEC_GSS, "----> RPCSEC_GSS svc=%u RPCSEC_GSS_SVC_NONE=%u RPCSEC_GSS_SVC_INTEGRITY=%u RPCSEC_GSS_SVC_PRIVACY=%u", gd->sec.svc, RPCSEC_GSS_SVC_NONE, RPCSEC_GSS_SVC_INTEGRITY, RPCSEC_GSS_SVC_PRIVACY); memcpy(&ptr, (void *)gd->ctx + 4, 4); LogFullDebug(COMPONENT_RPCSEC_GSS, "----> Client=%s length=%lu Qop=%u established=%u gss_ctx_id=%p|%p", (char *)gd->cname.value, gd->cname.length, gd->established, gd->sec.qop, gd->ctx, ptr); if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE) { LogFullDebug(COMPONENT_DISPATCH, "Error in gss_oid_to_str: %u|%u", maj_stat, min_stat); } else { LogFullDebug(COMPONENT_RPCSEC_GSS, "----> Client mech=%s len=%lu", (char *)oidbuff.value, oidbuff.length); // Release the string (void)gss_release_buffer(&min_stat, &oidbuff); } } LogFullDebug(COMPONENT_RPCSEC_GSS, "Mapping principal %s to uid/gid", (char *)gd->cname.value); memcpy(principal, gd->cname.value, gd->cname.length); principal[gd->cname.length] = 0; /* Convert to uid */ if(!principal2uid(principal, &user_credentials->caller_uid)) { LogWarn(COMPONENT_IDMAPPER, "WARNING: Could not map principal to uid; mapping principal " "to anonymous uid/gid"); /* For compatibility with Linux knfsd, we set the uid/gid * to anonymous when a name->uid mapping can't be found. */ user_credentials->caller_uid = pexport->anonymous_uid; user_credentials->caller_gid = pexport->anonymous_gid; /* No alternate groups for "nobody" */ user_credentials->caller_glen = 0 ; user_credentials->caller_garray = NULL ; return TRUE; } if(uidgidmap_get(user_credentials->caller_uid, &user_credentials->caller_gid) != ID_MAPPER_SUCCESS) { LogMajor(COMPONENT_DISPATCH, "FAILURE: Could not resolve uidgid map for %u", user_credentials->caller_uid); user_credentials->caller_gid = -1; } LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u", (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid); user_credentials->caller_glen = 0; user_credentials->caller_garray = 0; break; #endif /* _USE_GSSRPC */ default: LogFullDebug(COMPONENT_DISPATCH, "FAILURE: Request xid=%u, has unsupported authentication %d", rpcxid, ptr_req->rq_cred.oa_flavor); /* Reject the request for weak authentication and return to worker */ return FALSE; break; } /* switch( ptr_req->rq_cred.oa_flavor ) */ return TRUE; }
int main(int argc, char *argv[]) { gss_OID_set mechs; OM_uint32 major, minor; size_t i; major = gss_indicate_mechs(&minor, &mechs); if (GSS_ERROR(major)) { displayStatus("gss_indicate_mechs", major, minor); return major; } for (i = 0; i < mechs->count; i++) { gss_buffer_desc oidstr = GSS_C_EMPTY_BUFFER; gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER; gss_OID oid = GSS_C_NO_OID; major = gss_oid_to_str(&minor, &mechs->elements[i], &oidstr); if (GSS_ERROR(major)) continue; major = gss_inquire_saslname_for_mech(&minor, &mechs->elements[i], &sasl_mech_name, &mech_name, &mech_description); if (GSS_ERROR(major)) { gss_release_buffer(&minor, &oidstr); continue; } printf("-------------------------------------------------------------" "-----------------\n"); printf("OID : %.*s\n", (int)oidstr.length, (char *)oidstr.value); printf("SASL mech : %.*s\n", (int)sasl_mech_name.length, (char *)sasl_mech_name.value); printf("Mech name : %.*s\n", (int)mech_name.length, (char *)mech_name.value); printf("Mech desc : %.*s\n", (int)mech_description.length, (char *)mech_description.value); dumpMechAttrs(&minor, &mechs->elements[i]); printf("-------------------------------------------------------------" "-----------------\n"); if (GSS_ERROR(gss_inquire_mech_for_saslname(&minor, &sasl_mech_name, &oid))) { displayStatus("gss_inquire_mech_for_saslname", major, minor); } else if (oid == GSS_C_NO_OID || (oid->length != mechs->elements[i].length && memcmp(oid->elements, mechs->elements[i].elements, oid->length) != 0)) { gss_release_buffer(&minor, &oidstr); (void) gss_oid_to_str(&minor, oid, &oidstr); fprintf(stderr, "Got different OID %.*s for mechanism %.*s\n", (int)oidstr.length, (char *)oidstr.value, (int)sasl_mech_name.length, (char *)sasl_mech_name.value); } gss_release_buffer(&minor, &oidstr); gss_release_buffer(&minor, &sasl_mech_name); gss_release_buffer(&minor, &mech_name); gss_release_buffer(&minor, &mech_description); } gss_release_oid_set(&minor, &mechs); return GSS_ERROR(major) ? 1 : 0; }
DWORD VMCARESTVerifyKrbAuth( PVMCA_AUTHORIZATION_PARAM pAuthorization, PVMCA_ACCESS_TOKEN* ppAccessToken ) { DWORD dwError = 0; PSTR pszNegotiate = NULL; PSTR pszDecode = NULL; PSTR pszUser = NULL; char *pszToken = NULL; int nLength = 0; OM_uint32 major_status; OM_uint32 minor_status; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER; gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; gss_name_t client_name = GSS_C_NO_NAME; static gss_OID_desc gss_spnego_mech_oid_desc = {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; static gss_OID gss_spnego_mech_oid = &gss_spnego_mech_oid_desc; gss_cred_id_t server_creds; pszNegotiate = pAuthorization->pszAuthorizationToken; if ( IsNullOrEmptyString(pszNegotiate) ) { dwError = EACCES; BAIL_ON_VMREST_ERROR(dwError); } if (!strcmp(pszNegotiate,"testing")) // TODO: REMOVE // TODO: DO NOT CHECK IN {// Kerberos backdoor for testing dwError = VMCARESTMakeKrbAccessToken(ppAccessToken); BAIL_ON_VMREST_ERROR(dwError); goto cleanup; } dwError = base64_decode( pszNegotiate, &pszDecode, &nLength ); BAIL_ON_VMREST_ERROR(dwError); dwError = server_acquire_creds( "HTTP", &gss_spnego_mech_oid_desc, &server_creds ); BAIL_ON_VMREST_ERROR(dwError); input_token.length = nLength; input_token.value = pszDecode; major_status = gss_accept_sec_context( &minor_status, &gss_context, server_creds, &input_token, GSS_C_NO_CHANNEL_BINDINGS, &client_name, &gss_spnego_mech_oid, &output_token, NULL, NULL, NULL ); if (GSS_ERROR(major_status) ) { //TODO: insert show error dwError = EACCES; BAIL_ON_VMREST_ERROR(dwError); } if (output_token.length) { dwError = make_negotiate_token(&output_token, &pszToken); BAIL_ON_VMREST_ERROR(dwError); } if (major_status == GSS_S_CONTINUE_NEEDED) { OM_uint32 min2; gss_buffer_desc mech_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc gss_msg = GSS_C_EMPTY_BUFFER; gss_buffer_desc minor_msg = GSS_C_EMPTY_BUFFER; OM_uint32 msg_ctx = 0; PSTR pszError = NULL; gss_oid_to_str(&min2, gss_spnego_mech_oid, &mech_msg); gss_display_status(&min2, major_status, GSS_C_GSS_CODE, gss_spnego_mech_oid, &msg_ctx, &gss_msg); gss_display_status(&min2, minor_status, GSS_C_MECH_CODE, gss_spnego_mech_oid, &msg_ctx, &minor_msg); VMCAAllocateStringPrintfA(&pszError, "gss_rc[%d:%*s] mech[%*s] minor[%u:%*s]", major_status, (int)gss_msg.length, (const char *)(gss_msg.value?gss_msg.value:""), (int)mech_msg.length, (const char *)(mech_msg.value?mech_msg.value:""), minor_status, (int)minor_msg.length, (const char *)(minor_msg.value?minor_msg.value:"")); gss_release_buffer(&min2, &mech_msg); gss_release_buffer(&min2, &gss_msg); gss_release_buffer(&min2, &minor_msg); } if (major_status == GSS_S_COMPLETE) { gss_display_name(&minor_status, client_name, &display_name, NULL); dwError = VMCAAllocateStringA(display_name.value, &pszUser); BAIL_ON_VMREST_ERROR(dwError); } dwError = VMCARESTMakeKrbAccessToken(ppAccessToken); BAIL_ON_VMREST_ERROR(dwError); cleanup: if (pszUser) { VMCA_SAFE_FREE_MEMORY(pszUser); } return dwError; error: goto cleanup; }
static bool_t svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr) { struct svc_rpc_gss_data *gd; struct rpc_gss_cred *gc; gss_buffer_desc recv_tok, seqbuf; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; log_debug("in svcauth_gss_accept_context()"); gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth); gc = (struct rpc_gss_cred *)rqst->rq_clntcred; memset(gr, 0, sizeof(*gr)); /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); if (!svc_getargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok)) return (FALSE); gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, &mech, &gr->gr_token, &ret_flags, NULL, NULL); svc_freeargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok); log_status("accept_sec_context", gr->gr_major, gr->gr_minor); if (gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED) { badauth(gr->gr_major, gr->gr_minor, rqst->rq_xprt); gd->ctx = GSS_C_NO_CONTEXT; goto errout; } gr->gr_ctx.value = "xxxx"; gr->gr_ctx.length = 4; /* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version... */ gr->gr_win = sizeof(gd->seqmask) * 8; /* Save client info. */ gd->sec.mech = mech; gd->sec.qop = GSS_C_QOP_DEFAULT; gd->sec.svc = gc->gc_svc; gd->seq = gc->gc_seq; gd->win = gr->gr_win; if (gr->gr_major == GSS_S_COMPLETE) { #ifdef SPKM /* spkm3: no src_name (anonymous) */ if(!g_OID_equal(gss_mech_spkm3, mech)) { #endif maj_stat = gss_display_name(&min_stat, gd->client_name, &gd->cname, &gd->sec.mech); #ifdef SPKM } #endif if (maj_stat != GSS_S_COMPLETE) { log_status("display_name", maj_stat, min_stat); goto errout; } #ifdef DEBUG #ifdef HAVE_HEIMDAL log_debug("accepted context for %.*s with " "<mech {}, qop %d, svc %d>", gd->cname.length, (char *)gd->cname.value, gd->sec.qop, gd->sec.svc); #else { gss_buffer_desc mechname; gss_oid_to_str(&min_stat, mech, &mechname); log_debug("accepted context for %.*s with " "<mech %.*s, qop %d, svc %d>", gd->cname.length, (char *)gd->cname.value, mechname.length, (char *)mechname.value, gd->sec.qop, gd->sec.svc); gss_release_buffer(&min_stat, &mechname); } #endif #endif /* DEBUG */ seq = htonl(gr->gr_win); seqbuf.value = &seq; seqbuf.length = sizeof(seq); gss_release_buffer(&min_stat, &gd->checksum); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &gd->checksum); if (maj_stat != GSS_S_COMPLETE) { goto errout; } rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS; rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value; rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length; } return (TRUE); errout: gss_release_buffer(&min_stat, &gr->gr_token); return (FALSE); }
/* * Function: server_establish_context * * Purpose: establishses a GSS-API context as a specified service with * an incoming client, and returns the context handle and associated * client name * * Arguments: * * s (r) an established TCP connection to the client * service_creds (r) server credentials, from gss_acquire_cred * context (w) the established GSS-API context * client_name (w) the client's ASCII name * * Returns: 0 on success, -1 on failure * * Effects: * * Any valid client request is accepted. If a context is established, * its handle is returned in context and the client name is returned * in client_name and 0 is returned. If unsuccessful, an error * message is displayed and -1 is returned. */ static int server_establish_context(int s, gss_cred_id_t server_creds, gss_ctx_id_t *context, gss_buffer_t client_name, OM_uint32 *ret_flags) { gss_buffer_desc send_tok, recv_tok; gss_name_t client; gss_OID doid; OM_uint32 maj_stat, min_stat, acc_sec_min_stat; gss_buffer_desc oid_name; int token_flags; if (recv_token(s, &token_flags, &recv_tok) < 0) return -1; if (recv_tok.value) { free(recv_tok.value); recv_tok.value = NULL; } if (!(token_flags & TOKEN_NOOP)) { if (logfile) fprintf(logfile, "Expected NOOP token, got %d token instead\n", token_flags); return -1; } *context = GSS_C_NO_CONTEXT; if (token_flags & TOKEN_CONTEXT_NEXT) { do { if (recv_token(s, &token_flags, &recv_tok) < 0) return -1; if (verbose && logfile) { fprintf(logfile, "Received token (size=%d): \n", (int) recv_tok.length); print_token(&recv_tok); } maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, server_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, &doid, &send_tok, ret_flags, NULL, /* time_rec */ NULL); /* del_cred_handle */ if (recv_tok.value) { free(recv_tok.value); recv_tok.value = NULL; } if (send_tok.length != 0) { if (verbose && logfile) { fprintf(logfile, "Sending accept_sec_context token (size=%d):\n", (int) send_tok.length); print_token(&send_tok); } if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) { if (logfile) fprintf(logfile, "failure sending token\n"); return -1; } (void) gss_release_buffer(&min_stat, &send_tok); } if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { display_status("accepting context", maj_stat, acc_sec_min_stat); if (*context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER); return -1; } if (verbose && logfile) { if (maj_stat == GSS_S_CONTINUE_NEEDED) fprintf(logfile, "continue needed...\n"); else fprintf(logfile, "\n"); fflush(logfile); } } while (maj_stat == GSS_S_CONTINUE_NEEDED); /* display the flags */ display_ctx_flags(*ret_flags); if (verbose && logfile) { maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name); if (maj_stat != GSS_S_COMPLETE) { display_status("converting oid->string", maj_stat, min_stat); return -1; } fprintf(logfile, "Accepted connection using mechanism OID %.*s.\n", (int) oid_name.length, (char *) oid_name.value); (void) gss_release_buffer(&min_stat, &oid_name); } maj_stat = gss_display_name(&min_stat, client, client_name, &doid); if (maj_stat != GSS_S_COMPLETE) { display_status("displaying name", maj_stat, min_stat); return -1; } enumerateAttributes(&min_stat, client, TRUE); showLocalIdentity(&min_stat, client); maj_stat = gss_release_name(&min_stat, &client); if (maj_stat != GSS_S_COMPLETE) { display_status("releasing name", maj_stat, min_stat); return -1; } } else { client_name->length = *ret_flags = 0; if (logfile) fprintf(logfile, "Accepted unauthenticated connection.\n"); } return 0; }