1*da6c28aaSamw /* 2*da6c28aaSamw * CDDL HEADER START 3*da6c28aaSamw * 4*da6c28aaSamw * The contents of this file are subject to the terms of the 5*da6c28aaSamw * Common Development and Distribution License (the "License"). 6*da6c28aaSamw * You may not use this file except in compliance with the License. 7*da6c28aaSamw * 8*da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10*da6c28aaSamw * See the License for the specific language governing permissions 11*da6c28aaSamw * and limitations under the License. 12*da6c28aaSamw * 13*da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14*da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16*da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17*da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18*da6c28aaSamw * 19*da6c28aaSamw * CDDL HEADER END 20*da6c28aaSamw */ 21*da6c28aaSamw /* 22*da6c28aaSamw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*da6c28aaSamw * Use is subject to license terms. 24*da6c28aaSamw */ 25*da6c28aaSamw 26*da6c28aaSamw #pragma ident "%Z%%M% %I% %E% SMI" 27*da6c28aaSamw 28*da6c28aaSamw 29*da6c28aaSamw /* 30*da6c28aaSamw * NT Token library (kernel/user) 31*da6c28aaSamw */ 32*da6c28aaSamw 33*da6c28aaSamw #ifdef _KERNEL 34*da6c28aaSamw #include <sys/types.h> 35*da6c28aaSamw #include <sys/ddi.h> 36*da6c28aaSamw #include <sys/sunddi.h> 37*da6c28aaSamw #include <sys/ksynch.h> 38*da6c28aaSamw #include <sys/cmn_err.h> 39*da6c28aaSamw #include <sys/time.h> 40*da6c28aaSamw #include <sys/kmem.h> 41*da6c28aaSamw #else /* _KERNEL */ 42*da6c28aaSamw #include <stdlib.h> 43*da6c28aaSamw #include <strings.h> 44*da6c28aaSamw #include <thread.h> 45*da6c28aaSamw #include <synch.h> 46*da6c28aaSamw #include <syslog.h> 47*da6c28aaSamw #include <time.h> 48*da6c28aaSamw #include <arpa/inet.h> 49*da6c28aaSamw #include <sys/varargs.h> 50*da6c28aaSamw #include <smbsrv/alloc.h> 51*da6c28aaSamw #endif /* _KERNEL */ 52*da6c28aaSamw 53*da6c28aaSamw #include <sys/socket.h> 54*da6c28aaSamw #include <netinet/in.h> 55*da6c28aaSamw 56*da6c28aaSamw #include <smbsrv/alloc.h> 57*da6c28aaSamw #include <smbsrv/string.h> 58*da6c28aaSamw #include <smbsrv/smbinfo.h> 59*da6c28aaSamw #include <smbsrv/smb_token.h> 60*da6c28aaSamw #include <smbsrv/smb_xdr.h> 61*da6c28aaSamw 62*da6c28aaSamw #ifndef _KERNEL 63*da6c28aaSamw #include <assert.h> 64*da6c28aaSamw #define ASSERT assert 65*da6c28aaSamw void (*smb_token_logfunc)(int, const char *, ...) = syslog; 66*da6c28aaSamw int smb_token_errlog = LOG_ERR; 67*da6c28aaSamw int smb_token_infolog = LOG_INFO; 68*da6c28aaSamw #else /* _KERNEL */ 69*da6c28aaSamw void (*smb_token_logfunc)(int, const char *, ...) = cmn_err; 70*da6c28aaSamw int smb_token_errlog = CE_WARN; 71*da6c28aaSamw int smb_token_infolog = CE_NOTE; 72*da6c28aaSamw #endif /* _KERNEL */ 73*da6c28aaSamw 74*da6c28aaSamw int smb_token_debug = 0; 75*da6c28aaSamw 76*da6c28aaSamw #ifdef _KERNEL 77*da6c28aaSamw extern char *inet_ntop(int, const void *, char *, int); 78*da6c28aaSamw #endif /* _KERNEL */ 79*da6c28aaSamw 80*da6c28aaSamw /* 81*da6c28aaSamw * Returns -1 on error. Otherwise, returns 0. 82*da6c28aaSamw */ 83*da6c28aaSamw int 84*da6c28aaSamw smb_token_tobuf(smb_dr_user_ctx_t *usr, char *buf, int len) 85*da6c28aaSamw { 86*da6c28aaSamw char ipaddr_buf[INET_ADDRSTRLEN]; 87*da6c28aaSamw 88*da6c28aaSamw if (!usr) { 89*da6c28aaSamw (void) strcpy(buf, "N/A"); 90*da6c28aaSamw return (-1); 91*da6c28aaSamw } 92*da6c28aaSamw 93*da6c28aaSamw (void) inet_ntop(AF_INET, (char *)&usr->du_ipaddr, ipaddr_buf, 94*da6c28aaSamw sizeof (ipaddr_buf)); 95*da6c28aaSamw (void) snprintf(buf, len, "%s\\%s %s (%s)", 96*da6c28aaSamw usr->du_domain ? usr->du_domain : "", 97*da6c28aaSamw usr->du_account ? usr->du_account : "", 98*da6c28aaSamw usr->du_workstation ? usr->du_workstation : "", 99*da6c28aaSamw ipaddr_buf); 100*da6c28aaSamw 101*da6c28aaSamw return (0); 102*da6c28aaSamw } 103*da6c28aaSamw 104*da6c28aaSamw /*PRINTFLIKE3*/ 105*da6c28aaSamw void 106*da6c28aaSamw smb_token_log(int level, smb_dr_user_ctx_t *usr, char *fmt, ...) 107*da6c28aaSamw { 108*da6c28aaSamw va_list ap; 109*da6c28aaSamw char *msg; 110*da6c28aaSamw int len; 111*da6c28aaSamw char tokenbuf[NTTOKEN_BASIC_INFO_MAXLEN]; 112*da6c28aaSamw 113*da6c28aaSamw msg = MEM_MALLOC("nttoken", 1024); 114*da6c28aaSamw if (!msg) { 115*da6c28aaSamw smb_token_logfunc(smb_token_errlog, "smb_token_log: " 116*da6c28aaSamw "resource shortage"); 117*da6c28aaSamw return; 118*da6c28aaSamw } 119*da6c28aaSamw 120*da6c28aaSamw if (usr) 121*da6c28aaSamw (void) smb_token_tobuf(usr, tokenbuf, sizeof (tokenbuf)); 122*da6c28aaSamw else 123*da6c28aaSamw (void) strcpy(tokenbuf, "UNKNOWN"); 124*da6c28aaSamw 125*da6c28aaSamw va_start(ap, fmt); 126*da6c28aaSamw (void) snprintf(msg, 1024, "Token[%s]: ", tokenbuf); 127*da6c28aaSamw len = strlen(msg); 128*da6c28aaSamw (void) vsnprintf(msg + len, 1024 - len, fmt, ap); 129*da6c28aaSamw va_end(ap); 130*da6c28aaSamw #ifdef _KERNEL 131*da6c28aaSamw cmn_err(level, "%s", msg); 132*da6c28aaSamw #else 133*da6c28aaSamw syslog(level, "%s", msg); 134*da6c28aaSamw #endif /* _KERNEL */ 135*da6c28aaSamw 136*da6c28aaSamw MEM_FREE("nttoken", msg); 137*da6c28aaSamw } 138*da6c28aaSamw 139*da6c28aaSamw #ifndef _KERNEL 140*da6c28aaSamw /* 141*da6c28aaSamw * smb_token_print 142*da6c28aaSamw * 143*da6c28aaSamw * Diagnostic routine to write the contents of a token to the log. 144*da6c28aaSamw */ 145*da6c28aaSamw void 146*da6c28aaSamw smb_token_print(smb_token_t *token) 147*da6c28aaSamw { 148*da6c28aaSamw smb_win_grps_t *w_grps; 149*da6c28aaSamw smb_posix_grps_t *x_grps; 150*da6c28aaSamw smb_sid_attrs_t *grp; 151*da6c28aaSamw char sidstr[128]; 152*da6c28aaSamw int i; 153*da6c28aaSamw 154*da6c28aaSamw if (token == NULL) 155*da6c28aaSamw return; 156*da6c28aaSamw 157*da6c28aaSamw smb_token_logfunc(smb_token_infolog, "Token for %s\\%s", 158*da6c28aaSamw (token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-", 159*da6c28aaSamw (token->tkn_account_name) ? token->tkn_account_name : "-NULL-"); 160*da6c28aaSamw 161*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " User->Attr: %d", 162*da6c28aaSamw token->tkn_user->i_sidattr.attrs); 163*da6c28aaSamw nt_sid_format2((nt_sid_t *)token->tkn_user->i_sidattr.sid, sidstr); 164*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " User->Sid: %s (id=%u)", 165*da6c28aaSamw sidstr, token->tkn_user->i_id); 166*da6c28aaSamw 167*da6c28aaSamw nt_sid_format2((nt_sid_t *)token->tkn_owner->i_sidattr.sid, sidstr); 168*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " Ownr->Sid: %s (id=%u)", 169*da6c28aaSamw sidstr, token->tkn_owner->i_id); 170*da6c28aaSamw 171*da6c28aaSamw nt_sid_format2((nt_sid_t *)token->tkn_primary_grp->i_sidattr.sid, 172*da6c28aaSamw sidstr); 173*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " PGrp->Sid: %s (id=%u)", 174*da6c28aaSamw sidstr, token->tkn_primary_grp->i_id); 175*da6c28aaSamw 176*da6c28aaSamw w_grps = token->tkn_win_grps; 177*da6c28aaSamw if (w_grps) { 178*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " Windows groups: %d", 179*da6c28aaSamw w_grps->wg_count); 180*da6c28aaSamw 181*da6c28aaSamw for (i = 0; i < w_grps->wg_count; ++i) { 182*da6c28aaSamw grp = &w_grps->wg_groups[i].i_sidattr; 183*da6c28aaSamw smb_token_logfunc(smb_token_infolog, 184*da6c28aaSamw " Grp[%d].Attr:%d", i, grp->attrs); 185*da6c28aaSamw if (w_grps->wg_groups[i].i_sidattr.sid) { 186*da6c28aaSamw nt_sid_format2((nt_sid_t *)grp->sid, sidstr); 187*da6c28aaSamw smb_token_logfunc(smb_token_infolog, 188*da6c28aaSamw " Grp[%d].Sid: %s (id=%u)", i, sidstr, 189*da6c28aaSamw w_grps->wg_groups[i].i_id); 190*da6c28aaSamw } 191*da6c28aaSamw } 192*da6c28aaSamw } 193*da6c28aaSamw else 194*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " No Windows groups"); 195*da6c28aaSamw 196*da6c28aaSamw x_grps = token->tkn_posix_grps; 197*da6c28aaSamw if (x_grps) { 198*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " Solaris groups: %d", 199*da6c28aaSamw x_grps->pg_ngrps); 200*da6c28aaSamw for (i = 0; i < x_grps->pg_ngrps; i++) 201*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " %u", 202*da6c28aaSamw x_grps->pg_grps[i]); 203*da6c28aaSamw } 204*da6c28aaSamw else 205*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " No Solaris groups"); 206*da6c28aaSamw 207*da6c28aaSamw if (token->tkn_privileges) 208*da6c28aaSamw smb_privset_log(token->tkn_privileges); 209*da6c28aaSamw else 210*da6c28aaSamw smb_token_logfunc(smb_token_infolog, " No privileges"); 211*da6c28aaSamw } 212*da6c28aaSamw #endif /* _KERNEL */ 213*da6c28aaSamw 214*da6c28aaSamw /* 215*da6c28aaSamw * smb_token_query_privilege 216*da6c28aaSamw * 217*da6c28aaSamw * Find out if the specified privilege is enable in the given 218*da6c28aaSamw * access token. 219*da6c28aaSamw */ 220*da6c28aaSamw int 221*da6c28aaSamw smb_token_query_privilege(smb_token_t *token, int priv_id) 222*da6c28aaSamw { 223*da6c28aaSamw smb_privset_t *privset; 224*da6c28aaSamw int i; 225*da6c28aaSamw 226*da6c28aaSamw if ((token == NULL) || (token->tkn_privileges == NULL)) 227*da6c28aaSamw return (0); 228*da6c28aaSamw 229*da6c28aaSamw privset = token->tkn_privileges; 230*da6c28aaSamw for (i = 0; privset->priv_cnt; i++) { 231*da6c28aaSamw if (privset->priv[i].luid.lo_part == priv_id) { 232*da6c28aaSamw if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED) 233*da6c28aaSamw return (1); 234*da6c28aaSamw else 235*da6c28aaSamw return (0); 236*da6c28aaSamw } 237*da6c28aaSamw } 238*da6c28aaSamw 239*da6c28aaSamw return (0); 240*da6c28aaSamw } 241*da6c28aaSamw 242*da6c28aaSamw #ifndef _KERNEL 243*da6c28aaSamw /* 244*da6c28aaSamw * smb_token_mkselfrel 245*da6c28aaSamw * 246*da6c28aaSamw * encode: structure -> flat buffer (buffer size) 247*da6c28aaSamw * Pre-condition: obj is non-null. 248*da6c28aaSamw */ 249*da6c28aaSamw uint8_t * 250*da6c28aaSamw smb_token_mkselfrel(smb_token_t *obj, uint32_t *len) 251*da6c28aaSamw { 252*da6c28aaSamw uint8_t *buf; 253*da6c28aaSamw XDR xdrs; 254*da6c28aaSamw 255*da6c28aaSamw if (!obj) { 256*da6c28aaSamw smb_token_logfunc(smb_token_errlog, 257*da6c28aaSamw "smb_token_mkselfrel: invalid parameter"); 258*da6c28aaSamw return (NULL); 259*da6c28aaSamw } 260*da6c28aaSamw 261*da6c28aaSamw *len = xdr_sizeof(xdr_smb_token_t, obj); 262*da6c28aaSamw buf = (uint8_t *)malloc(*len); 263*da6c28aaSamw if (!buf) { 264*da6c28aaSamw smb_token_logfunc(smb_token_errlog, 265*da6c28aaSamw "smb_token_mkselfrel: resource shortage"); 266*da6c28aaSamw return (NULL); 267*da6c28aaSamw } 268*da6c28aaSamw 269*da6c28aaSamw xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); 270*da6c28aaSamw 271*da6c28aaSamw if (!xdr_smb_token_t(&xdrs, obj)) { 272*da6c28aaSamw smb_token_logfunc(smb_token_errlog, 273*da6c28aaSamw "smb_token_mkselfrel: XDR encode error"); 274*da6c28aaSamw *len = 0; 275*da6c28aaSamw free(buf); 276*da6c28aaSamw buf = NULL; 277*da6c28aaSamw } 278*da6c28aaSamw 279*da6c28aaSamw xdr_destroy(&xdrs); 280*da6c28aaSamw return (buf); 281*da6c28aaSamw } 282*da6c28aaSamw 283*da6c28aaSamw /* 284*da6c28aaSamw * netr_client_mkabsolute 285*da6c28aaSamw * 286*da6c28aaSamw * decode: flat buffer -> structure 287*da6c28aaSamw */ 288*da6c28aaSamw netr_client_t * 289*da6c28aaSamw netr_client_mkabsolute(uint8_t *buf, uint32_t len) 290*da6c28aaSamw { 291*da6c28aaSamw netr_client_t *obj; 292*da6c28aaSamw XDR xdrs; 293*da6c28aaSamw 294*da6c28aaSamw xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); 295*da6c28aaSamw obj = (netr_client_t *)malloc(sizeof (netr_client_t)); 296*da6c28aaSamw if (!obj) { 297*da6c28aaSamw smb_token_logfunc(smb_token_errlog, "netr_client_mkabsolute: " 298*da6c28aaSamw "resource shortage"); 299*da6c28aaSamw xdr_destroy(&xdrs); 300*da6c28aaSamw return (NULL); 301*da6c28aaSamw } 302*da6c28aaSamw 303*da6c28aaSamw bzero(obj, sizeof (netr_client_t)); 304*da6c28aaSamw if (!xdr_netr_client_t(&xdrs, obj)) { 305*da6c28aaSamw smb_token_logfunc(smb_token_errlog, "netr_client_mkabsolute: " 306*da6c28aaSamw "XDR decode error"); 307*da6c28aaSamw free(obj); 308*da6c28aaSamw obj = NULL; 309*da6c28aaSamw } 310*da6c28aaSamw 311*da6c28aaSamw xdr_destroy(&xdrs); 312*da6c28aaSamw return (obj); 313*da6c28aaSamw } 314*da6c28aaSamw #else /* _KERNEL */ 315*da6c28aaSamw /* 316*da6c28aaSamw * smb_token_mkabsolute 317*da6c28aaSamw * 318*da6c28aaSamw * decode: flat buffer -> structure 319*da6c28aaSamw */ 320*da6c28aaSamw smb_token_t * 321*da6c28aaSamw smb_token_mkabsolute(uint8_t *buf, uint32_t len) 322*da6c28aaSamw { 323*da6c28aaSamw smb_token_t *obj; 324*da6c28aaSamw XDR xdrs; 325*da6c28aaSamw 326*da6c28aaSamw xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); 327*da6c28aaSamw obj = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP); 328*da6c28aaSamw 329*da6c28aaSamw if (!xdr_smb_token_t(&xdrs, obj)) { 330*da6c28aaSamw smb_token_logfunc(smb_token_errlog, "smb_token_mkabsolute: XDR " 331*da6c28aaSamw "decode error"); 332*da6c28aaSamw kmem_free(obj, sizeof (smb_token_t)); 333*da6c28aaSamw obj = NULL; 334*da6c28aaSamw } 335*da6c28aaSamw 336*da6c28aaSamw xdr_destroy(&xdrs); 337*da6c28aaSamw return (obj); 338*da6c28aaSamw } 339*da6c28aaSamw 340*da6c28aaSamw /* 341*da6c28aaSamw * netr_client_mkselfrel 342*da6c28aaSamw * 343*da6c28aaSamw * encode: structure -> flat buffer (buffer size) 344*da6c28aaSamw * Pre-condition: obj is non-null. 345*da6c28aaSamw */ 346*da6c28aaSamw uint8_t * 347*da6c28aaSamw netr_client_mkselfrel(netr_client_t *obj, uint32_t *len) 348*da6c28aaSamw { 349*da6c28aaSamw uint8_t *buf; 350*da6c28aaSamw XDR xdrs; 351*da6c28aaSamw 352*da6c28aaSamw *len = xdr_sizeof(xdr_netr_client_t, obj); 353*da6c28aaSamw buf = kmem_alloc(*len, KM_SLEEP); 354*da6c28aaSamw 355*da6c28aaSamw xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); 356*da6c28aaSamw 357*da6c28aaSamw if (!xdr_netr_client_t(&xdrs, obj)) { 358*da6c28aaSamw smb_token_logfunc(smb_token_errlog, "netr_client_mkselfrel: " 359*da6c28aaSamw "XDR encode error"); 360*da6c28aaSamw kmem_free(buf, *len); 361*da6c28aaSamw *len = 0; 362*da6c28aaSamw buf = NULL; 363*da6c28aaSamw } 364*da6c28aaSamw 365*da6c28aaSamw xdr_destroy(&xdrs); 366*da6c28aaSamw return (buf); 367*da6c28aaSamw } 368*da6c28aaSamw 369*da6c28aaSamw void 370*da6c28aaSamw smb_token_free(smb_token_t *token) 371*da6c28aaSamw { 372*da6c28aaSamw if (!token) 373*da6c28aaSamw return; 374*da6c28aaSamw 375*da6c28aaSamw /* 376*da6c28aaSamw * deallocate any pointer field of an access token object 377*da6c28aaSamw * using xdr_free since they are created by the XDR decode 378*da6c28aaSamw * operation. 379*da6c28aaSamw */ 380*da6c28aaSamw xdr_free(xdr_smb_token_t, (char *)token); 381*da6c28aaSamw kmem_free(token, sizeof (smb_token_t)); 382*da6c28aaSamw } 383*da6c28aaSamw #endif /* _KERNEL */ 384