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