OM_uint32 _gss_spnego_sign (OM_uint32 * minor_status, gss_ctx_id_t context_handle, int qop_req, gss_buffer_t message_buffer, gss_buffer_t message_token ) { gssspnego_ctx ctx; *minor_status = 0; if (context_handle == GSS_C_NO_CONTEXT) { return GSS_S_NO_CONTEXT; } ctx = (gssspnego_ctx)context_handle; if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { return GSS_S_NO_CONTEXT; } return gss_sign(minor_status, ctx->negotiated_ctx_id, qop_req, message_buffer, message_token); }
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); }
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); }
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); }
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); }