/* * Build the SPNEGO "hint" token based on the * configured authentication mechanisms. * (NTLMSSP, and maybe Kerberos) */ void smbd_get_authconf(smb_kmod_cfg_t *kcfg) { SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL; uchar_t *pBuf = kcfg->skc_negtok; uint32_t *pBufLen = &kcfg->skc_negtok_len; ulong_t tLen = sizeof (kcfg->skc_negtok); int rc; rc = spnegoCreateNegTokenHint(MechTypeList, MechTypeCnt, (uchar_t *)IgnoreSPN, &hSpnegoToken); if (rc != SPNEGO_E_SUCCESS) { syslog(LOG_DEBUG, "smb_config_get_negtok: " "spnegoCreateNegTokenHint, rc=%d", rc); *pBufLen = 0; return; } rc = spnegoTokenGetBinary(hSpnegoToken, pBuf, &tLen); if (rc != SPNEGO_E_SUCCESS) { syslog(LOG_DEBUG, "smb_config_get_negtok: " "spnegoTokenGetBinary, rc=%d", rc); *pBufLen = 0; } else { *pBufLen = (uint32_t)tLen; } spnegoFreeData(hSpnegoToken); }
void smbd_authctx_destroy(authsvc_context_t *ctx) { if (ctx->ctx_socket != -1) { (void) close(ctx->ctx_socket); ctx->ctx_socket = -1; } if (ctx->ctx_token != NULL) smb_token_destroy(ctx->ctx_token); if (ctx->ctx_itoken != NULL) spnegoFreeData(ctx->ctx_itoken); if (ctx->ctx_otoken != NULL) spnegoFreeData(ctx->ctx_otoken); free(ctx->ctx_irawbuf); free(ctx->ctx_orawbuf); free(ctx->ctx_ibodybuf); free(ctx->ctx_obodybuf); free(ctx); }
/* * Handle a security blob we've received from the client. * Incoming type: LSA_MTYPE_ESNEXT * Outgoing types: LSA_MTYPE_ES_CONT, LSA_MTYPE_ES_DONE, * LSA_MTYPE_ERROR */ static int smbd_authsvc_esnext(authsvc_context_t *ctx) { int rc; /* * Make sure LSA_MTYPE_ESFIRST was handled * previously, so we have a work function. */ if (ctx->ctx_mh_work == NULL) return (NT_STATUS_INVALID_PARAMETER); if (ctx->ctx_mech_oid == special_mech_raw_NTLMSSP) { rc = smbd_raw_ntlmssp_esnext(ctx); return (rc); } /* * Cleanup state from previous calls. */ if (ctx->ctx_itoken != NULL) { spnegoFreeData(ctx->ctx_itoken); ctx->ctx_itoken = NULL; } /* * Parse the SPNEGO token, check its type. */ rc = spnegoInitFromBinary(ctx->ctx_irawbuf, ctx->ctx_irawlen, &ctx->ctx_itoken); if (rc != 0) return (NT_STATUS_INVALID_PARAMETER); rc = spnegoGetTokenType(ctx->ctx_itoken, &ctx->ctx_itoktype); if (rc != 0) return (NT_STATUS_INVALID_PARAMETER); if (ctx->ctx_itoktype != SPNEGO_TOKEN_TARG) return (NT_STATUS_INVALID_PARAMETER); rc = smbd_authsvc_escmn(ctx); return (rc); }
/* * Build the SPNEGO "hint" token based on the * configured authentication mechanisms. * (NTLMSSP, and maybe Kerberos) */ void smbd_get_authconf(smb_kmod_cfg_t *kcfg) { SPNEGO_MECH_OID *mechList = MechTypeList; int mechCnt = MechTypeCnt; SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL; uchar_t *pBuf = kcfg->skc_negtok; uint32_t *pBufLen = &kcfg->skc_negtok_len; ulong_t tLen = sizeof (kcfg->skc_negtok); int rc; /* * In workgroup mode, skip Kerberos. */ if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) { mechList += MECH_OID_IDX_NTLMSSP; mechCnt -= MECH_OID_IDX_NTLMSSP; } rc = spnegoCreateNegTokenHint(mechList, mechCnt, (uchar_t *)IgnoreSPN, &hSpnegoToken); if (rc != SPNEGO_E_SUCCESS) { syslog(LOG_DEBUG, "smb_config_get_negtok: " "spnegoCreateNegTokenHint, rc=%d", rc); *pBufLen = 0; return; } rc = spnegoTokenGetBinary(hSpnegoToken, pBuf, &tLen); if (rc != SPNEGO_E_SUCCESS) { syslog(LOG_DEBUG, "smb_config_get_negtok: " "spnegoTokenGetBinary, rc=%d", rc); *pBufLen = 0; } else { *pBufLen = (uint32_t)tLen; } spnegoFreeData(hSpnegoToken); }
static int smbd_authsvc_escmn(authsvc_context_t *ctx) { SPNEGO_MECH_OID oid; ulong_t toklen; int rc; /* * Cleanup state from previous calls. */ if (ctx->ctx_otoken != NULL) { spnegoFreeData(ctx->ctx_otoken); ctx->ctx_otoken = NULL; } /* * Extract the payload (mech token). */ toklen = ctx->ctx_ibodylen; rc = spnegoGetMechToken(ctx->ctx_itoken, ctx->ctx_ibodybuf, &toklen); switch (rc) { case SPNEGO_E_SUCCESS: break; case SPNEGO_E_ELEMENT_UNAVAILABLE: toklen = 0; break; case SPNEGO_E_BUFFER_TOO_SMALL: return (NT_STATUS_BUFFER_TOO_SMALL); default: return (NT_STATUS_INTERNAL_ERROR); } ctx->ctx_ibodylen = toklen; /* * Now that we have the incoming "body" (mech. token), * call the back-end mech-specific work function to * create the outgoing "body" (mech. token). * * The worker must fill in: ctx->ctx_negresult, * and: ctx->ctx_obodylen, but ctx->ctx_obodybuf * is optional, and is typically NULL after the * final message of an auth sequence, where * negresult == spnego_negresult_complete. */ rc = ctx->ctx_mh_work(ctx); if (rc != 0) return (rc); /* * Wrap the outgoing body in a negTokenTarg SPNEGO token. * The selected mech. OID is returned only when the * incoming token was of type SPNEGO_TOKEN_INIT. */ if (ctx->ctx_itoktype == SPNEGO_TOKEN_INIT) { /* tell the client the selected mech. */ oid = ctx->ctx_mech_oid; } else { /* Ommit the "supported mech." field. */ oid = spnego_mech_oid_NotUsed; } /* * Determine the spnego "negresult" from the * reply message type (from the work func). */ switch (ctx->ctx_orawtype) { case LSA_MTYPE_ERROR: ctx->ctx_negresult = spnego_negresult_rejected; break; case LSA_MTYPE_ES_DONE: ctx->ctx_negresult = spnego_negresult_success; break; case LSA_MTYPE_ES_CONT: ctx->ctx_negresult = spnego_negresult_incomplete; break; default: return (-1); } rc = spnegoCreateNegTokenTarg( oid, ctx->ctx_negresult, ctx->ctx_obodybuf, /* may be NULL */ ctx->ctx_obodylen, NULL, 0, &ctx->ctx_otoken); /* * Convert the SPNEGO token into binary form, * writing it to the output buffer. */ toklen = smbd_authsvc_bufsize; rc = spnegoTokenGetBinary(ctx->ctx_otoken, (uchar_t *)ctx->ctx_orawbuf, &toklen); if (rc) rc = NT_STATUS_INTERNAL_ERROR; ctx->ctx_orawlen = (uint_t)toklen; return (rc); }