#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <note.h>
#include <net/if.h>
#include <net/route.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <pthread.h>
#include <syslog.h>
#include <ucred.h>
#include <priv.h>
#include <smbsrv/libsmb.h>
#include <netsmb/spnego.h>
#include "smbd.h"
#include "smbd_authsvc.h"
#define special_mech_raw_NTLMSSP (spnego_mech_oid_NTLMSSP + 100)
static struct sockaddr_un smbauth_sockname = {
AF_UNIX, SMB_AUTHSVC_SOCKNAME };
typedef struct spnego_mech_handler {
int mh_oid;
int (*mh_init)(authsvc_context_t *);
int (*mh_work)(authsvc_context_t *);
void (*mh_fini)(authsvc_context_t *);
} spnego_mech_handler_t;
static int smbd_authsock_create(void);
static void smbd_authsock_destroy(void);
static void *smbd_authsvc_listen(void *);
static void *smbd_authsvc_work(void *);
static void smbd_authsvc_flood(void);
static int smbd_authsvc_oldreq(authsvc_context_t *);
static int smbd_authsvc_clinfo(authsvc_context_t *);
static int smbd_authsvc_esfirst(authsvc_context_t *);
static int smbd_authsvc_esnext(authsvc_context_t *);
static int smbd_authsvc_escmn(authsvc_context_t *);
static int smbd_authsvc_newmech(authsvc_context_t *);
static int smbd_authsvc_gettoken(authsvc_context_t *);
static int smbd_raw_ntlmssp_esfirst(authsvc_context_t *);
static int smbd_raw_ntlmssp_esnext(authsvc_context_t *);
int smbd_authsvc_bufsize = 65000;
static mutex_t smbd_authsvc_mutex = DEFAULTMUTEX;
int smbd_authsvc_maxthread = SMB_AUTHSVC_MAXTHREAD + 32;
int smbd_authsvc_thrcnt = 0;
int smbd_authsvc_hiwat = 0;
#ifdef DEBUG
int smbd_authsvc_slowdown = 0;
#endif
static const spnego_mech_handler_t
mech_table[] = {
{
spnego_mech_oid_Kerberos_V5,
smbd_krb5ssp_init,
smbd_krb5ssp_work,
smbd_krb5ssp_fini
},
{
spnego_mech_oid_Kerberos_V5_Legacy,
smbd_krb5ssp_init,
smbd_krb5ssp_work,
smbd_krb5ssp_fini
},
#define MECH_TBL_IDX_NTLMSSP 2
{
spnego_mech_oid_NTLMSSP,
smbd_ntlmssp_init,
smbd_ntlmssp_work,
smbd_ntlmssp_fini
},
{
spnego_mech_oid_NotUsed,
NULL, NULL, NULL
},
};
static const spnego_mech_handler_t
smbd_auth_mech_raw_ntlmssp = {
special_mech_raw_NTLMSSP,
smbd_ntlmssp_init,
smbd_ntlmssp_work,
smbd_ntlmssp_fini
};
int
smbd_authsvc_start(void)
{
pthread_attr_t attr;
pthread_t tid;
int rc;
rc = smbd_authsock_create();
if (rc)
return (rc);
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
rc = pthread_create(&tid, &attr, smbd_authsvc_listen, &smbd);
(void) pthread_attr_destroy(&attr);
if (rc) {
smbd_authsock_destroy();
return (rc);
}
smbd.s_authsvc_tid = tid;
return (0);
}
void
smbd_authsvc_stop(void)
{
if (smbd.s_authsvc_tid != 0) {
(void) pthread_kill(smbd.s_authsvc_tid, SIGTERM);
smbd.s_authsvc_tid = 0;
}
}
static int
smbd_authsock_create(void)
{
int sock = -1;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
smbd_report("authsvc, socket create failed, %d", errno);
return (errno);
}
(void) unlink(smbauth_sockname.sun_path);
if (bind(sock, (struct sockaddr *)&smbauth_sockname,
sizeof (smbauth_sockname)) < 0) {
smbd_report("authsvc, socket bind failed, %d", errno);
(void) close(sock);
return (errno);
}
if (listen(sock, SOMAXCONN) < 0) {
smbd_report("authsvc, socket listen failed, %d", errno);
(void) close(sock);
return (errno);
}
smbd.s_authsvc_sock = sock;
return (0);
}
static void
smbd_authsock_destroy(void)
{
int fid;
if ((fid = smbd.s_authsvc_sock) != -1) {
smbd.s_authsvc_sock = -1;
(void) close(fid);
}
}
#ifndef FKSMBD
static boolean_t
authsock_has_priv(int sock)
{
ucred_t *uc = NULL;
const priv_set_t *ps = NULL;
boolean_t ret = B_FALSE;
pid_t clpid;
if (getpeerucred(sock, &uc) != 0) {
smbd_report("authsvc: getpeerucred err %d", errno);
return (B_FALSE);
}
clpid = ucred_getpid(uc);
ps = ucred_getprivset(uc, PRIV_EFFECTIVE);
if (ps == NULL) {
smbd_report("authsvc: ucred_getprivset failed");
goto out;
}
if (priv_ismember(ps, PRIV_SYS_SMB)) {
ret = B_TRUE;
goto out;
}
if (smbd.s_debug) {
smbd_report("authsvc: non-privileged client "
"PID = %d UID = %d",
(int)clpid, ucred_getruid(uc));
}
out:
if (uc != NULL)
ucred_free(uc);
return (ret);
}
#endif
static void *
smbd_authsvc_listen(void *arg)
{
authsvc_context_t *ctx;
pthread_attr_t attr;
pthread_t tid;
socklen_t slen;
int ls, ns, rc;
_NOTE(ARGUNUSED(arg))
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ls = smbd.s_authsvc_sock;
for (;;) {
slen = 0;
ns = accept(ls, NULL, &slen);
if (ns < 0) {
switch (errno) {
case ECONNABORTED:
continue;
case EINTR:
goto out;
default:
smbd_report("authsvc, socket accept failed,"
" %d", errno);
goto out;
}
}
#ifndef FKSMBD
if (!authsock_has_priv(ns)) {
close(ns);
continue;
}
#endif
(void) mutex_lock(&smbd_authsvc_mutex);
if (smbd_authsvc_thrcnt >= smbd_authsvc_maxthread) {
(void) mutex_unlock(&smbd_authsvc_mutex);
(void) close(ns);
smbd_authsvc_flood();
continue;
}
smbd_authsvc_thrcnt++;
if (smbd_authsvc_hiwat < smbd_authsvc_thrcnt)
smbd_authsvc_hiwat = smbd_authsvc_thrcnt;
(void) mutex_unlock(&smbd_authsvc_mutex);
ctx = smbd_authctx_create();
if (ctx == NULL) {
smbd_report("authsvc, can't allocate context");
(void) mutex_lock(&smbd_authsvc_mutex);
smbd_authsvc_thrcnt--;
(void) mutex_unlock(&smbd_authsvc_mutex);
(void) close(ns);
smbd_nomem();
}
ctx->ctx_socket = ns;
rc = pthread_create(&tid, &attr, smbd_authsvc_work, ctx);
if (rc) {
smbd_report("authsvc, thread create failed, %d", rc);
(void) mutex_lock(&smbd_authsvc_mutex);
smbd_authsvc_thrcnt--;
(void) mutex_unlock(&smbd_authsvc_mutex);
smbd_authctx_destroy(ctx);
ctx = NULL;
smbd_nomem();
}
ctx = NULL;
(void) pthread_detach(tid);
}
out:
(void) pthread_attr_destroy(&attr);
smbd_authsock_destroy();
return (NULL);
}
static void
smbd_authsvc_flood(void)
{
static uint_t count;
static time_t last_report;
time_t now = time(NULL);
count++;
if (last_report + 60 < now) {
last_report = now;
smbd_report("authsvc: flooded %u", count);
count = 0;
}
}
authsvc_context_t *
smbd_authctx_create(void)
{
authsvc_context_t *ctx;
ctx = malloc(sizeof (*ctx));
if (ctx == NULL)
return (NULL);
bzero(ctx, sizeof (*ctx));
ctx->ctx_irawlen = smbd_authsvc_bufsize;
ctx->ctx_irawbuf = malloc(ctx->ctx_irawlen);
ctx->ctx_orawlen = smbd_authsvc_bufsize;
ctx->ctx_orawbuf = malloc(ctx->ctx_orawlen);
if (ctx->ctx_irawbuf == NULL || ctx->ctx_orawbuf == NULL)
goto errout;
ctx->ctx_ibodylen = smbd_authsvc_bufsize;
ctx->ctx_ibodybuf = malloc(ctx->ctx_ibodylen);
ctx->ctx_obodylen = smbd_authsvc_bufsize;
ctx->ctx_obodybuf = malloc(ctx->ctx_obodylen);
if (ctx->ctx_ibodybuf == NULL || ctx->ctx_obodybuf == NULL)
goto errout;
return (ctx);
errout:
smbd_authctx_destroy(ctx);
return (NULL);
}
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);
}
static struct timeval recv_tmo = { 30, 0 };
static struct timeval send_tmo = { 15, 0 };
static void *
smbd_authsvc_work(void *arg)
{
authsvc_context_t *ctx = arg;
smb_lsa_msg_hdr_t hdr;
int sock = ctx->ctx_socket;
int len, rc;
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
(char *)&send_tmo, sizeof (send_tmo)) != 0) {
smbd_report("authsvc_work: set set timeout: %m");
goto out;
}
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
(char *)&recv_tmo, sizeof (recv_tmo)) != 0) {
smbd_report("authsvc_work: set recv timeout: %m");
goto out;
}
for (;;) {
len = recv(sock, &hdr, sizeof (hdr), MSG_WAITALL);
if (len <= 0) {
break;
}
if (len != sizeof (hdr)) {
smbd_report("authsvc_work: read header failed");
break;
}
if (hdr.lmh_msglen > smbd_authsvc_bufsize) {
smbd_report("authsvc_work: msg too large");
break;
}
if (hdr.lmh_msglen > 0) {
len = recv(sock, ctx->ctx_irawbuf, hdr.lmh_msglen,
MSG_WAITALL);
if (len != hdr.lmh_msglen) {
smbd_report("authsvc_work: read mesg failed");
break;
}
}
ctx->ctx_irawtype = hdr.lmh_msgtype;
ctx->ctx_irawlen = hdr.lmh_msglen;
ctx->ctx_orawlen = smbd_authsvc_bufsize;
ctx->ctx_ibodylen = smbd_authsvc_bufsize;
ctx->ctx_obodylen = smbd_authsvc_bufsize;
rc = smbd_authsvc_dispatch(ctx);
if (rc)
break;
hdr.lmh_msgtype = ctx->ctx_orawtype;
hdr.lmh_msglen = ctx->ctx_orawlen;
len = send(sock, &hdr, sizeof (hdr), 0);
if (len != sizeof (hdr)) {
smbd_report("authsvc_work: send failed");
break;
}
if (ctx->ctx_orawlen > 0) {
len = send(sock, ctx->ctx_orawbuf,
ctx->ctx_orawlen, 0);
if (len != ctx->ctx_orawlen) {
smbd_report("authsvc_work: send failed");
break;
}
}
}
out:
if (ctx->ctx_mh_fini)
(ctx->ctx_mh_fini)(ctx);
smbd_authctx_destroy(ctx);
(void) mutex_lock(&smbd_authsvc_mutex);
smbd_authsvc_thrcnt--;
(void) mutex_unlock(&smbd_authsvc_mutex);
return (NULL);
}
int
smbd_authsvc_dispatch(authsvc_context_t *ctx)
{
int rc;
switch (ctx->ctx_irawtype) {
case LSA_MTYPE_OLDREQ:
#ifdef DEBUG
if (smbd_authsvc_slowdown)
(void) sleep(smbd_authsvc_slowdown);
#endif
rc = smbd_authsvc_oldreq(ctx);
break;
case LSA_MTYPE_CLINFO:
rc = smbd_authsvc_clinfo(ctx);
break;
case LSA_MTYPE_ESFIRST:
rc = smbd_authsvc_esfirst(ctx);
break;
case LSA_MTYPE_ESNEXT:
#ifdef DEBUG
if (smbd_authsvc_slowdown)
(void) sleep(smbd_authsvc_slowdown);
#endif
rc = smbd_authsvc_esnext(ctx);
break;
case LSA_MTYPE_GETTOK:
rc = smbd_authsvc_gettoken(ctx);
break;
case LSA_MTYPE_OK:
case LSA_MTYPE_ERROR:
case LSA_MTYPE_TOKEN:
case LSA_MTYPE_ES_CONT:
case LSA_MTYPE_ES_DONE:
default:
return (-1);
}
if (rc == NT_STATUS_NO_MEMORY)
smbd_nomem();
if (rc != 0) {
smb_lsa_eresp_t *er = ctx->ctx_orawbuf;
ctx->ctx_orawtype = LSA_MTYPE_ERROR;
ctx->ctx_orawlen = sizeof (*er);
er->ler_ntstatus = rc;
er->ler_errclass = 0;
er->ler_errcode = 0;
}
return (0);
}
static int
smbd_authsvc_oldreq(authsvc_context_t *ctx)
{
smb_logon_t user_info;
XDR xdrs;
smb_token_t *token = NULL;
int rc = 0;
bzero(&user_info, sizeof (user_info));
xdrmem_create(&xdrs, ctx->ctx_irawbuf, ctx->ctx_irawlen,
XDR_DECODE);
if (!smb_logon_xdr(&xdrs, &user_info)) {
xdr_destroy(&xdrs);
return (NT_STATUS_INVALID_PARAMETER);
}
xdr_destroy(&xdrs);
token = smbd_user_auth_logon(&user_info);
xdr_free(smb_logon_xdr, (char *)&user_info);
if (token == NULL) {
rc = user_info.lg_status;
if (rc == 0)
rc = NT_STATUS_INTERNAL_ERROR;
return (rc);
}
ctx->ctx_token = token;
return (rc);
}
static int
smbd_authsvc_clinfo(authsvc_context_t *ctx)
{
if (ctx->ctx_irawlen != sizeof (smb_lsa_clinfo_t))
return (NT_STATUS_INTERNAL_ERROR);
(void) memcpy(&ctx->ctx_clinfo, ctx->ctx_irawbuf,
sizeof (smb_lsa_clinfo_t));
ctx->ctx_orawtype = LSA_MTYPE_OK;
ctx->ctx_orawlen = 0;
return (0);
}
static int
smbd_authsvc_esfirst(authsvc_context_t *ctx)
{
const spnego_mech_handler_t *mh;
int idx, pref, rc;
int best_pref = 1000;
int best_mhidx = -1;
if (ctx->ctx_irawlen < 8) {
smbd_report("authsvc: short blob");
return (NT_STATUS_INVALID_PARAMETER);
}
if (bcmp(ctx->ctx_irawbuf, "NTLMSSP", 8) == 0) {
rc = smbd_raw_ntlmssp_esfirst(ctx);
return (rc);
}
rc = spnegoInitFromBinary(ctx->ctx_irawbuf,
ctx->ctx_irawlen, &ctx->ctx_itoken);
if (rc != 0) {
smbd_report("authsvc: spnego parse failed");
return (NT_STATUS_INVALID_PARAMETER);
}
rc = spnegoGetTokenType(ctx->ctx_itoken, &ctx->ctx_itoktype);
if (rc != 0) {
smbd_report("authsvc: spnego get token type failed");
return (NT_STATUS_INVALID_PARAMETER);
}
if (ctx->ctx_itoktype != SPNEGO_TOKEN_INIT) {
smbd_report("authsvc: spnego wrong token type %d",
ctx->ctx_itoktype);
return (NT_STATUS_INVALID_PARAMETER);
}
idx = 0;
mh = mech_table;
if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) {
idx = MECH_TBL_IDX_NTLMSSP;
mh = &mech_table[idx];
}
for (; mh->mh_init != NULL; idx++, mh++) {
if (spnegoIsMechTypeAvailable(ctx->ctx_itoken,
mh->mh_oid, &pref) != 0)
continue;
if (pref < best_pref) {
best_pref = pref;
best_mhidx = idx;
}
}
if (best_mhidx == -1) {
smbd_report("authsvc: no supported spnego mechanism");
return (NT_STATUS_INVALID_PARAMETER);
}
mh = &mech_table[best_mhidx];
ctx->ctx_mech_oid = mh->mh_oid;
ctx->ctx_mh_work = mh->mh_work;
ctx->ctx_mh_fini = mh->mh_fini;
rc = mh->mh_init(ctx);
if (rc != 0) {
smbd_report("authsvc: mech init failed");
return (rc);
}
if (best_pref != 0) {
rc = smbd_authsvc_newmech(ctx);
} else {
rc = smbd_authsvc_escmn(ctx);
}
return (rc);
}
static int
smbd_authsvc_esnext(authsvc_context_t *ctx)
{
int rc;
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);
}
if (ctx->ctx_itoken != NULL) {
spnegoFreeData(ctx->ctx_itoken);
ctx->ctx_itoken = NULL;
}
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);
}
static int
smbd_authsvc_escmn(authsvc_context_t *ctx)
{
SPNEGO_MECH_OID oid;
ulong_t toklen;
int rc;
if (ctx->ctx_otoken != NULL) {
spnegoFreeData(ctx->ctx_otoken);
ctx->ctx_otoken = NULL;
}
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;
rc = ctx->ctx_mh_work(ctx);
if (rc != 0)
return (rc);
if (ctx->ctx_itoktype == SPNEGO_TOKEN_INIT) {
oid = ctx->ctx_mech_oid;
} else {
oid = spnego_mech_oid_NotUsed;
}
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,
ctx->ctx_obodylen,
NULL, 0,
&ctx->ctx_otoken);
if (rc != 0)
return (NT_STATUS_INTERNAL_ERROR);
toklen = smbd_authsvc_bufsize;
rc = spnegoTokenGetBinary(ctx->ctx_otoken,
(uchar_t *)ctx->ctx_orawbuf, &toklen);
if (rc != 0)
rc = NT_STATUS_INTERNAL_ERROR;
ctx->ctx_orawlen = (uint_t)toklen;
return (rc);
}
static int
smbd_authsvc_newmech(authsvc_context_t *ctx)
{
ulong_t toklen;
int rc;
ctx->ctx_ibodylen = 0;
ctx->ctx_orawtype = LSA_MTYPE_ES_CONT;
ctx->ctx_obodylen = 0;
ctx->ctx_negresult = spnego_negresult_request_mic;
rc = spnegoCreateNegTokenTarg(
ctx->ctx_mech_oid,
ctx->ctx_negresult,
NULL, 0,
NULL, 0,
&ctx->ctx_otoken);
if (rc != 0)
return (NT_STATUS_INTERNAL_ERROR);
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);
}
static int
smbd_raw_ntlmssp_esfirst(authsvc_context_t *ctx)
{
const spnego_mech_handler_t *mh;
int rc;
mh = &smbd_auth_mech_raw_ntlmssp;
rc = mh->mh_init(ctx);
if (rc != 0)
return (rc);
ctx->ctx_mech_oid = mh->mh_oid;
ctx->ctx_mh_work = mh->mh_work;
ctx->ctx_mh_fini = mh->mh_fini;
rc = smbd_raw_ntlmssp_esnext(ctx);
return (rc);
}
static int
smbd_raw_ntlmssp_esnext(authsvc_context_t *ctx)
{
int rc;
ctx->ctx_ibodylen = ctx->ctx_irawlen;
(void) memcpy(ctx->ctx_ibodybuf,
ctx->ctx_irawbuf, ctx->ctx_irawlen);
rc = ctx->ctx_mh_work(ctx);
ctx->ctx_orawlen = ctx->ctx_obodylen;
(void) memcpy(ctx->ctx_orawbuf,
ctx->ctx_obodybuf, ctx->ctx_obodylen);
return (rc);
}
static int
smbd_authsvc_gettoken(authsvc_context_t *ctx)
{
XDR xdrs;
smb_token_t *token = NULL;
int rc = 0;
int len;
if ((token = ctx->ctx_token) == NULL)
return (NT_STATUS_ACCESS_DENIED);
len = xdr_sizeof(smb_token_xdr, token);
if (len > ctx->ctx_orawlen) {
if ((ctx->ctx_orawbuf = realloc(ctx->ctx_orawbuf, len)) ==
NULL) {
return (NT_STATUS_NO_MEMORY);
}
}
ctx->ctx_orawtype = LSA_MTYPE_TOKEN;
ctx->ctx_orawlen = len;
xdrmem_create(&xdrs, ctx->ctx_orawbuf, len, XDR_ENCODE);
if (!smb_token_xdr(&xdrs, token))
rc = NT_STATUS_INTERNAL_ERROR;
xdr_destroy(&xdrs);
return (rc);
}
static SPNEGO_MECH_OID MechTypeList[] = {
spnego_mech_oid_Kerberos_V5,
spnego_mech_oid_Kerberos_V5_Legacy,
#define MECH_OID_IDX_NTLMSSP 2
spnego_mech_oid_NTLMSSP,
};
static int MechTypeCnt = sizeof (MechTypeList) /
sizeof (MechTypeList[0]);
static char IgnoreSPN[] = "not_defined_in_RFC4178@please_ignore";
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;
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);
}