1*5772Sas200622 /* 2*5772Sas200622 * CDDL HEADER START 3*5772Sas200622 * 4*5772Sas200622 * The contents of this file are subject to the terms of the 5*5772Sas200622 * Common Development and Distribution License (the "License"). 6*5772Sas200622 * You may not use this file except in compliance with the License. 7*5772Sas200622 * 8*5772Sas200622 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5772Sas200622 * or http://www.opensolaris.org/os/licensing. 10*5772Sas200622 * See the License for the specific language governing permissions 11*5772Sas200622 * and limitations under the License. 12*5772Sas200622 * 13*5772Sas200622 * When distributing Covered Code, include this CDDL HEADER in each 14*5772Sas200622 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5772Sas200622 * If applicable, add the following below this CDDL HEADER, with the 16*5772Sas200622 * fields enclosed by brackets "[]" replaced with your own identifying 17*5772Sas200622 * information: Portions Copyright [yyyy] [name of copyright owner] 18*5772Sas200622 * 19*5772Sas200622 * CDDL HEADER END 20*5772Sas200622 */ 21*5772Sas200622 /* 22*5772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*5772Sas200622 * Use is subject to license terms. 24*5772Sas200622 */ 25*5772Sas200622 26*5772Sas200622 #pragma ident "%Z%%M% %I% %E% SMI" 27*5772Sas200622 28*5772Sas200622 29*5772Sas200622 #include <synch.h> 30*5772Sas200622 #include <stdio.h> 31*5772Sas200622 #include <unistd.h> 32*5772Sas200622 #include <string.h> 33*5772Sas200622 #include <strings.h> 34*5772Sas200622 #include <assert.h> 35*5772Sas200622 36*5772Sas200622 #include <smbsrv/libsmb.h> 37*5772Sas200622 #include <smbsrv/ndr.h> 38*5772Sas200622 #include <smbsrv/mlrpc.h> 39*5772Sas200622 #include <smbsrv/ntsid.h> 40*5772Sas200622 41*5772Sas200622 42*5772Sas200622 /* 43*5772Sas200622 * Global list of allocated handles. Handles are used in various 44*5772Sas200622 * server-side RPC functions: typically, issued when a service is 45*5772Sas200622 * opened and obsoleted when it is closed. Clients should treat 46*5772Sas200622 * handles as opaque data. 47*5772Sas200622 */ 48*5772Sas200622 static ndr_handle_t *ndr_handle_list; 49*5772Sas200622 static mutex_t ndr_handle_lock; 50*5772Sas200622 51*5772Sas200622 /* 52*5772Sas200622 * Table of registered services. 53*5772Sas200622 */ 54*5772Sas200622 #define NDL_MAX_SERVICES 32 55*5772Sas200622 static mlrpc_service_t *mlrpc_services[NDL_MAX_SERVICES]; 56*5772Sas200622 57*5772Sas200622 58*5772Sas200622 struct mlrpc_stub_table * 59*5772Sas200622 mlrpc_find_stub_in_svc(mlrpc_service_t *msvc, int opnum) 60*5772Sas200622 { 61*5772Sas200622 struct mlrpc_stub_table *ste; 62*5772Sas200622 63*5772Sas200622 for (ste = msvc->stub_table; ste->func; ste++) { 64*5772Sas200622 if (ste->opnum == opnum) 65*5772Sas200622 return (ste); 66*5772Sas200622 } 67*5772Sas200622 68*5772Sas200622 return (NULL); 69*5772Sas200622 } 70*5772Sas200622 71*5772Sas200622 mlrpc_service_t * 72*5772Sas200622 mlrpc_find_service_by_name(const char *name) 73*5772Sas200622 { 74*5772Sas200622 mlrpc_service_t *msvc; 75*5772Sas200622 int i; 76*5772Sas200622 77*5772Sas200622 for (i = 0; i < NDL_MAX_SERVICES; i++) { 78*5772Sas200622 if ((msvc = mlrpc_services[i]) == NULL) 79*5772Sas200622 continue; 80*5772Sas200622 81*5772Sas200622 if (strcasecmp(name, msvc->name) != 0) 82*5772Sas200622 continue; 83*5772Sas200622 84*5772Sas200622 mlndo_printf(0, 0, "%s %s", msvc->name, msvc->desc); 85*5772Sas200622 return (msvc); 86*5772Sas200622 } 87*5772Sas200622 88*5772Sas200622 return (NULL); 89*5772Sas200622 } 90*5772Sas200622 91*5772Sas200622 mlrpc_service_t * 92*5772Sas200622 mlrpc_find_service_by_uuids(ndr_uuid_t *as_uuid, int as_vers, 93*5772Sas200622 ndr_uuid_t *ts_uuid, int ts_vers) 94*5772Sas200622 { 95*5772Sas200622 mlrpc_service_t *msvc; 96*5772Sas200622 char abstract_syntax[128]; 97*5772Sas200622 char transfer_syntax[128]; 98*5772Sas200622 int i; 99*5772Sas200622 100*5772Sas200622 if (as_uuid) 101*5772Sas200622 mlrpc_uuid_to_str(as_uuid, abstract_syntax); 102*5772Sas200622 103*5772Sas200622 if (ts_uuid) 104*5772Sas200622 mlrpc_uuid_to_str(ts_uuid, transfer_syntax); 105*5772Sas200622 106*5772Sas200622 for (i = 0; i < NDL_MAX_SERVICES; i++) { 107*5772Sas200622 if ((msvc = mlrpc_services[i]) == NULL) 108*5772Sas200622 continue; 109*5772Sas200622 110*5772Sas200622 if (as_uuid) { 111*5772Sas200622 if (msvc->abstract_syntax_uuid == 0) 112*5772Sas200622 continue; 113*5772Sas200622 114*5772Sas200622 if (msvc->abstract_syntax_version != as_vers) 115*5772Sas200622 continue; 116*5772Sas200622 117*5772Sas200622 if (strcasecmp(abstract_syntax, 118*5772Sas200622 msvc->abstract_syntax_uuid)) 119*5772Sas200622 continue; 120*5772Sas200622 } 121*5772Sas200622 122*5772Sas200622 if (ts_uuid) { 123*5772Sas200622 if (msvc->transfer_syntax_uuid == 0) 124*5772Sas200622 continue; 125*5772Sas200622 126*5772Sas200622 if (msvc->transfer_syntax_version != ts_vers) 127*5772Sas200622 continue; 128*5772Sas200622 129*5772Sas200622 if (strcasecmp(transfer_syntax, 130*5772Sas200622 msvc->transfer_syntax_uuid)) 131*5772Sas200622 continue; 132*5772Sas200622 } 133*5772Sas200622 134*5772Sas200622 mlndo_printf(0, 0, "%s %s", msvc->name, msvc->desc); 135*5772Sas200622 return (msvc); 136*5772Sas200622 } 137*5772Sas200622 138*5772Sas200622 return (NULL); 139*5772Sas200622 } 140*5772Sas200622 141*5772Sas200622 /* 142*5772Sas200622 * Register a service. 143*5772Sas200622 * 144*5772Sas200622 * Returns: 145*5772Sas200622 * 0 Success 146*5772Sas200622 * -1 Duplicate service 147*5772Sas200622 * -2 Duplicate name 148*5772Sas200622 * -3 Table overflow 149*5772Sas200622 */ 150*5772Sas200622 int 151*5772Sas200622 mlrpc_register_service(mlrpc_service_t *msvc) 152*5772Sas200622 { 153*5772Sas200622 mlrpc_service_t *p; 154*5772Sas200622 int free_slot = -1; 155*5772Sas200622 int i; 156*5772Sas200622 157*5772Sas200622 for (i = 0; i < NDL_MAX_SERVICES; i++) { 158*5772Sas200622 if ((p = mlrpc_services[i]) == NULL) { 159*5772Sas200622 if (free_slot < 0) 160*5772Sas200622 free_slot = i; 161*5772Sas200622 continue; 162*5772Sas200622 } 163*5772Sas200622 164*5772Sas200622 if (p == msvc) 165*5772Sas200622 return (-1); 166*5772Sas200622 167*5772Sas200622 if (strcasecmp(p->name, msvc->name) == 0) 168*5772Sas200622 return (-2); 169*5772Sas200622 } 170*5772Sas200622 171*5772Sas200622 if (free_slot < 0) 172*5772Sas200622 return (-3); 173*5772Sas200622 174*5772Sas200622 mlrpc_services[free_slot] = msvc; 175*5772Sas200622 return (0); 176*5772Sas200622 } 177*5772Sas200622 178*5772Sas200622 void 179*5772Sas200622 mlrpc_unregister_service(mlrpc_service_t *msvc) 180*5772Sas200622 { 181*5772Sas200622 int i; 182*5772Sas200622 183*5772Sas200622 for (i = 0; i < NDL_MAX_SERVICES; i++) { 184*5772Sas200622 if (mlrpc_services[i] == msvc) 185*5772Sas200622 mlrpc_services[i] = NULL; 186*5772Sas200622 } 187*5772Sas200622 } 188*5772Sas200622 189*5772Sas200622 int 190*5772Sas200622 mlrpc_list_services(char *buffer, int bufsize) 191*5772Sas200622 { 192*5772Sas200622 mlrpc_service_t *msvc; 193*5772Sas200622 smb_ctxbuf_t ctx; 194*5772Sas200622 int i; 195*5772Sas200622 196*5772Sas200622 (void) smb_ctxbuf_init(&ctx, (uint8_t *)buffer, bufsize); 197*5772Sas200622 198*5772Sas200622 for (i = 0; i < NDL_MAX_SERVICES; i++) { 199*5772Sas200622 if ((msvc = mlrpc_services[i]) != 0) { 200*5772Sas200622 (void) smb_ctxbuf_printf(&ctx, "%-16s %s\n", 201*5772Sas200622 msvc->name, msvc->desc); 202*5772Sas200622 } 203*5772Sas200622 } 204*5772Sas200622 205*5772Sas200622 return (smb_ctxbuf_len(&ctx)); 206*5772Sas200622 } 207*5772Sas200622 208*5772Sas200622 /* 209*5772Sas200622 * Allocate a handle for use with the server-side RPC functions. 210*5772Sas200622 * The handle contains the machine SID and an incrementing counter, 211*5772Sas200622 * which should make each handle unique. 212*5772Sas200622 * 213*5772Sas200622 * An arbitrary caller context can be associated with the handle 214*5772Sas200622 * via data; it will not be dereferenced by the handle API. 215*5772Sas200622 * 216*5772Sas200622 * The uuid for the new handle is returned after it has been added 217*5772Sas200622 * to the global handle list. 218*5772Sas200622 */ 219*5772Sas200622 ndr_hdid_t * 220*5772Sas200622 ndr_hdalloc(const ndr_xa_t *xa, const void *data) 221*5772Sas200622 { 222*5772Sas200622 static ndr_hdid_t uuid; 223*5772Sas200622 ndr_handle_t *hd; 224*5772Sas200622 nt_sid_t *sid; 225*5772Sas200622 226*5772Sas200622 if ((hd = malloc(sizeof (ndr_handle_t))) == NULL) 227*5772Sas200622 return (NULL); 228*5772Sas200622 229*5772Sas200622 if (uuid.data[1] == 0) { 230*5772Sas200622 if ((sid = nt_domain_local_sid()) == NULL) 231*5772Sas200622 return (NULL); 232*5772Sas200622 233*5772Sas200622 uuid.data[0] = 0; 234*5772Sas200622 uuid.data[1] = 0; 235*5772Sas200622 uuid.data[2] = sid->SubAuthority[1]; 236*5772Sas200622 uuid.data[3] = sid->SubAuthority[2]; 237*5772Sas200622 uuid.data[4] = sid->SubAuthority[3]; 238*5772Sas200622 } 239*5772Sas200622 240*5772Sas200622 ++uuid.data[1]; 241*5772Sas200622 242*5772Sas200622 bcopy(&uuid, &hd->nh_id, sizeof (ndr_hdid_t)); 243*5772Sas200622 hd->nh_fid = xa->fid; 244*5772Sas200622 hd->nh_svc = xa->binding->service; 245*5772Sas200622 hd->nh_data = (void *)data; 246*5772Sas200622 247*5772Sas200622 (void) mutex_lock(&ndr_handle_lock); 248*5772Sas200622 hd->nh_next = ndr_handle_list; 249*5772Sas200622 ndr_handle_list = hd; 250*5772Sas200622 (void) mutex_unlock(&ndr_handle_lock); 251*5772Sas200622 252*5772Sas200622 return (&hd->nh_id); 253*5772Sas200622 } 254*5772Sas200622 255*5772Sas200622 /* 256*5772Sas200622 * Remove a handle from the global list and free it. 257*5772Sas200622 */ 258*5772Sas200622 void 259*5772Sas200622 ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id) 260*5772Sas200622 { 261*5772Sas200622 mlrpc_service_t *svc = xa->binding->service; 262*5772Sas200622 ndr_handle_t *hd; 263*5772Sas200622 ndr_handle_t **pphd; 264*5772Sas200622 265*5772Sas200622 assert(id); 266*5772Sas200622 267*5772Sas200622 (void) mutex_lock(&ndr_handle_lock); 268*5772Sas200622 pphd = &ndr_handle_list; 269*5772Sas200622 270*5772Sas200622 while (*pphd) { 271*5772Sas200622 hd = *pphd; 272*5772Sas200622 273*5772Sas200622 if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { 274*5772Sas200622 if (hd->nh_svc == svc) { 275*5772Sas200622 *pphd = hd->nh_next; 276*5772Sas200622 free(hd); 277*5772Sas200622 } 278*5772Sas200622 break; 279*5772Sas200622 } 280*5772Sas200622 281*5772Sas200622 pphd = &(*pphd)->nh_next; 282*5772Sas200622 } 283*5772Sas200622 284*5772Sas200622 (void) mutex_unlock(&ndr_handle_lock); 285*5772Sas200622 } 286*5772Sas200622 287*5772Sas200622 /* 288*5772Sas200622 * Lookup a handle by id. If the handle is in the list and it matches 289*5772Sas200622 * the specified service, a pointer to it is returned. Otherwise a null 290*5772Sas200622 * pointer is returned. 291*5772Sas200622 */ 292*5772Sas200622 ndr_handle_t * 293*5772Sas200622 ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id) 294*5772Sas200622 { 295*5772Sas200622 mlrpc_service_t *svc = xa->binding->service; 296*5772Sas200622 ndr_handle_t *hd; 297*5772Sas200622 298*5772Sas200622 assert(id); 299*5772Sas200622 (void) mutex_lock(&ndr_handle_lock); 300*5772Sas200622 hd = ndr_handle_list; 301*5772Sas200622 302*5772Sas200622 while (hd) { 303*5772Sas200622 if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { 304*5772Sas200622 if (hd->nh_svc != svc) 305*5772Sas200622 break; 306*5772Sas200622 (void) mutex_unlock(&ndr_handle_lock); 307*5772Sas200622 return (hd); 308*5772Sas200622 } 309*5772Sas200622 310*5772Sas200622 hd = hd->nh_next; 311*5772Sas200622 } 312*5772Sas200622 313*5772Sas200622 (void) mutex_unlock(&ndr_handle_lock); 314*5772Sas200622 return (NULL); 315*5772Sas200622 } 316*5772Sas200622 317*5772Sas200622 /* 318*5772Sas200622 * Called when a pipe is closed to release any associated handles. 319*5772Sas200622 */ 320*5772Sas200622 void 321*5772Sas200622 ndr_hdclose(int fid) 322*5772Sas200622 { 323*5772Sas200622 ndr_handle_t *hd; 324*5772Sas200622 ndr_handle_t **pphd; 325*5772Sas200622 326*5772Sas200622 (void) mutex_lock(&ndr_handle_lock); 327*5772Sas200622 pphd = &ndr_handle_list; 328*5772Sas200622 329*5772Sas200622 while (*pphd) { 330*5772Sas200622 hd = *pphd; 331*5772Sas200622 332*5772Sas200622 if (hd->nh_fid == fid) { 333*5772Sas200622 *pphd = hd->nh_next; 334*5772Sas200622 free(hd); 335*5772Sas200622 continue; 336*5772Sas200622 } 337*5772Sas200622 338*5772Sas200622 pphd = &(*pphd)->nh_next; 339*5772Sas200622 } 340*5772Sas200622 341*5772Sas200622 (void) mutex_unlock(&ndr_handle_lock); 342*5772Sas200622 } 343*5772Sas200622 344*5772Sas200622 void 345*5772Sas200622 mlrpc_uuid_to_str(ndr_uuid_t *uuid, char *str) 346*5772Sas200622 { 347*5772Sas200622 (void) sprintf(str, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", 348*5772Sas200622 uuid->data1, uuid->data2, uuid->data3, 349*5772Sas200622 uuid->data4[0], uuid->data4[1], 350*5772Sas200622 uuid->data4[2], uuid->data4[3], 351*5772Sas200622 uuid->data4[4], uuid->data4[5], 352*5772Sas200622 uuid->data4[6], uuid->data4[7]); 353*5772Sas200622 } 354*5772Sas200622 355*5772Sas200622 int 356*5772Sas200622 mlrpc_str_to_uuid(char *str, ndr_uuid_t *uuid) 357*5772Sas200622 { 358*5772Sas200622 char *p = str; 359*5772Sas200622 char *q; 360*5772Sas200622 char buf[4]; 361*5772Sas200622 int i; 362*5772Sas200622 363*5772Sas200622 uuid->data1 = strtoul(p, &p, 16); 364*5772Sas200622 if (*p != '-') 365*5772Sas200622 return (0); 366*5772Sas200622 p++; 367*5772Sas200622 368*5772Sas200622 uuid->data2 = strtol(p, &p, 16); 369*5772Sas200622 if (*p != '-') 370*5772Sas200622 return (0); 371*5772Sas200622 p++; 372*5772Sas200622 373*5772Sas200622 uuid->data3 = strtol(p, &p, 16); 374*5772Sas200622 if (*p != '-') 375*5772Sas200622 return (0); 376*5772Sas200622 p++; 377*5772Sas200622 378*5772Sas200622 for (i = 0; i < 8; i++) { 379*5772Sas200622 if (p[0] == 0 || p[1] == 0) 380*5772Sas200622 return (0); 381*5772Sas200622 382*5772Sas200622 buf[0] = *p++; 383*5772Sas200622 buf[1] = *p++; 384*5772Sas200622 buf[2] = 0; 385*5772Sas200622 uuid->data4[i] = strtol(buf, &q, 16); 386*5772Sas200622 if (*q != 0) 387*5772Sas200622 return (0); 388*5772Sas200622 } 389*5772Sas200622 390*5772Sas200622 if (*p != 0) 391*5772Sas200622 return (0); 392*5772Sas200622 393*5772Sas200622 return (1); 394*5772Sas200622 } 395*5772Sas200622 396*5772Sas200622 void 397*5772Sas200622 mlrpc_binding_pool_initialize(struct mlrpc_binding **headpp, 398*5772Sas200622 struct mlrpc_binding pool[], unsigned n_pool) 399*5772Sas200622 { 400*5772Sas200622 struct mlrpc_binding *head = NULL; 401*5772Sas200622 int ix; 402*5772Sas200622 403*5772Sas200622 for (ix = n_pool - 1; ix >= 0; ix--) { 404*5772Sas200622 pool[ix].next = head; 405*5772Sas200622 pool[ix].service = NULL; 406*5772Sas200622 pool[ix].p_cont_id = 0xffff; 407*5772Sas200622 pool[ix].instance_specific = 0; 408*5772Sas200622 head = &pool[ix]; 409*5772Sas200622 } 410*5772Sas200622 411*5772Sas200622 *headpp = head; 412*5772Sas200622 } 413*5772Sas200622 414*5772Sas200622 struct mlrpc_binding * 415*5772Sas200622 mlrpc_find_binding(struct mlrpc_xaction *mxa, mlrpc_p_context_id_t p_cont_id) 416*5772Sas200622 { 417*5772Sas200622 struct mlrpc_binding *mbind; 418*5772Sas200622 419*5772Sas200622 for (mbind = mxa->binding_list; mbind; mbind = mbind->next) { 420*5772Sas200622 if (mbind->service != NULL && 421*5772Sas200622 mbind->which_side == MLRPC_BIND_SIDE_SERVER && 422*5772Sas200622 mbind->p_cont_id == p_cont_id) 423*5772Sas200622 break; 424*5772Sas200622 } 425*5772Sas200622 426*5772Sas200622 return (mbind); 427*5772Sas200622 } 428*5772Sas200622 429*5772Sas200622 struct mlrpc_binding * 430*5772Sas200622 mlrpc_new_binding(struct mlrpc_xaction *mxa) 431*5772Sas200622 { 432*5772Sas200622 struct mlrpc_binding *mbind; 433*5772Sas200622 434*5772Sas200622 for (mbind = mxa->binding_list; mbind; mbind = mbind->next) { 435*5772Sas200622 if (mbind->service == NULL) 436*5772Sas200622 break; 437*5772Sas200622 } 438*5772Sas200622 439*5772Sas200622 return (mbind); 440*5772Sas200622 } 441