1*5331Samw /* 2*5331Samw * CDDL HEADER START 3*5331Samw * 4*5331Samw * The contents of this file are subject to the terms of the 5*5331Samw * Common Development and Distribution License (the "License"). 6*5331Samw * You may not use this file except in compliance with the License. 7*5331Samw * 8*5331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5331Samw * or http://www.opensolaris.org/os/licensing. 10*5331Samw * See the License for the specific language governing permissions 11*5331Samw * and limitations under the License. 12*5331Samw * 13*5331Samw * When distributing Covered Code, include this CDDL HEADER in each 14*5331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5331Samw * If applicable, add the following below this CDDL HEADER, with the 16*5331Samw * fields enclosed by brackets "[]" replaced with your own identifying 17*5331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 18*5331Samw * 19*5331Samw * CDDL HEADER END 20*5331Samw */ 21*5331Samw /* 22*5331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5331Samw * Use is subject to license terms. 24*5331Samw */ 25*5331Samw 26*5331Samw #pragma ident "%Z%%M% %I% %E% SMI" 27*5331Samw 28*5331Samw /* 29*5331Samw * Net DFS server side RPC service. 30*5331Samw */ 31*5331Samw 32*5331Samw #include <sys/types.h> 33*5331Samw #include <strings.h> 34*5331Samw #include <string.h> 35*5331Samw 36*5331Samw #include <smbsrv/libsmb.h> 37*5331Samw #include <smbsrv/lmerr.h> 38*5331Samw #include <smbsrv/lmdfs.h> 39*5331Samw #include <smbsrv/nmpipes.h> 40*5331Samw #include <smbsrv/nterror.h> 41*5331Samw #include <smbsrv/mlrpc.h> 42*5331Samw #include <smbsrv/ndl/netdfs.ndl> 43*5331Samw 44*5331Samw typedef struct { 45*5331Samw char *server; 46*5331Samw char *share; 47*5331Samw char *path; 48*5331Samw char *buf; 49*5331Samw } netdfs_unc_t; 50*5331Samw 51*5331Samw static int netdfs_unc_parse(struct mlrpc_xaction *, const char *, 52*5331Samw netdfs_unc_t *); 53*5331Samw 54*5331Samw static int netdfs_s_getver(void *, struct mlrpc_xaction *); 55*5331Samw static int netdfs_s_add(void *, struct mlrpc_xaction *); 56*5331Samw static int netdfs_s_remove(void *, struct mlrpc_xaction *); 57*5331Samw static int netdfs_s_setinfo(void *, struct mlrpc_xaction *); 58*5331Samw static int netdfs_s_getinfo(void *, struct mlrpc_xaction *); 59*5331Samw static int netdfs_s_enum(void *, struct mlrpc_xaction *); 60*5331Samw static int netdfs_s_move(void *, struct mlrpc_xaction *); 61*5331Samw static int netdfs_s_rename(void *, struct mlrpc_xaction *); 62*5331Samw static int netdfs_s_addstdroot(void *, struct mlrpc_xaction *); 63*5331Samw static int netdfs_s_remstdroot(void *, struct mlrpc_xaction *); 64*5331Samw static int netdfs_s_enumex(void *, struct mlrpc_xaction *); 65*5331Samw 66*5331Samw static mlrpc_stub_table_t netdfs_stub_table[] = { 67*5331Samw { netdfs_s_getver, NETDFS_OPNUM_GETVER }, 68*5331Samw { netdfs_s_add, NETDFS_OPNUM_ADD }, 69*5331Samw { netdfs_s_remove, NETDFS_OPNUM_REMOVE }, 70*5331Samw { netdfs_s_setinfo, NETDFS_OPNUM_SETINFO }, 71*5331Samw { netdfs_s_getinfo, NETDFS_OPNUM_GETINFO }, 72*5331Samw { netdfs_s_enum, NETDFS_OPNUM_ENUM }, 73*5331Samw { netdfs_s_rename, NETDFS_OPNUM_RENAME }, 74*5331Samw { netdfs_s_move, NETDFS_OPNUM_MOVE }, 75*5331Samw { netdfs_s_addstdroot, NETDFS_OPNUM_ADDSTDROOT }, 76*5331Samw { netdfs_s_remstdroot, NETDFS_OPNUM_REMSTDROOT }, 77*5331Samw { netdfs_s_enumex, NETDFS_OPNUM_ENUMEX }, 78*5331Samw {0} 79*5331Samw }; 80*5331Samw 81*5331Samw static mlrpc_service_t netdfs_service = { 82*5331Samw "NETDFS", /* name */ 83*5331Samw "DFS", /* desc */ 84*5331Samw "\\dfs", /* endpoint */ 85*5331Samw PIPE_NTSVCS, /* sec_addr_port */ 86*5331Samw NETDFS_ABSTRACT_UUID, NETDFS_ABSTRACT_VERS, 87*5331Samw NETDFS_TRANSFER_UUID, NETDFS_TRANSFER_VERS, 88*5331Samw 89*5331Samw 0, /* no bind_instance_size */ 90*5331Samw 0, /* no bind_req() */ 91*5331Samw 0, /* no unbind_and_close() */ 92*5331Samw 0, /* use generic_call_stub() */ 93*5331Samw 94*5331Samw &TYPEINFO(netdfs_interface), /* interface ti */ 95*5331Samw netdfs_stub_table /* stub_table */ 96*5331Samw }; 97*5331Samw 98*5331Samw /* 99*5331Samw * Register the NETDFS RPC interface with the RPC runtime library. 100*5331Samw * The service must be registered in order to use either the client 101*5331Samw * side or the server side functions. 102*5331Samw */ 103*5331Samw void 104*5331Samw netdfs_initialize(void) 105*5331Samw { 106*5331Samw (void) mlrpc_register_service(&netdfs_service); 107*5331Samw } 108*5331Samw 109*5331Samw /* 110*5331Samw * Return the version. 111*5331Samw * 112*5331Samw * We have to indicate that we emulate a Windows 2003 Server or the 113*5331Samw * client will not use the EnumEx RPC and this would limit support 114*5331Samw * to a single DFS root. 115*5331Samw */ 116*5331Samw /*ARGSUSED*/ 117*5331Samw static int 118*5331Samw netdfs_s_getver(void *arg, struct mlrpc_xaction *mxa) 119*5331Samw { 120*5331Samw struct netdfs_getver *param = arg; 121*5331Samw 122*5331Samw param->version = DFS_MANAGER_VERSION_W2K3; 123*5331Samw return (MLRPC_DRC_OK); 124*5331Samw } 125*5331Samw 126*5331Samw /* 127*5331Samw * Add a new volume or additional storage for an existing volume at 128*5331Samw * dfs_path. 129*5331Samw */ 130*5331Samw static int 131*5331Samw netdfs_s_add(void *arg, struct mlrpc_xaction *mxa) 132*5331Samw { 133*5331Samw struct netdfs_add *param = arg; 134*5331Samw netdfs_unc_t unc; 135*5331Samw DWORD status = ERROR_SUCCESS; 136*5331Samw 137*5331Samw if (param->dfs_path == NULL || param->server == NULL || 138*5331Samw param->share == NULL) { 139*5331Samw bzero(param, sizeof (struct netdfs_add)); 140*5331Samw param->status = ERROR_INVALID_PARAMETER; 141*5331Samw return (MLRPC_DRC_OK); 142*5331Samw } 143*5331Samw 144*5331Samw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 145*5331Samw status = ERROR_INVALID_PARAMETER; 146*5331Samw } else { 147*5331Samw if (unc.path == NULL) 148*5331Samw status = ERROR_BAD_PATHNAME; 149*5331Samw 150*5331Samw if (unc.share == NULL) 151*5331Samw status = ERROR_INVALID_SHARENAME; 152*5331Samw } 153*5331Samw 154*5331Samw if (param->status != ERROR_SUCCESS) { 155*5331Samw bzero(param, sizeof (struct netdfs_add)); 156*5331Samw param->status = status; 157*5331Samw return (MLRPC_DRC_OK); 158*5331Samw } 159*5331Samw 160*5331Samw bzero(param, sizeof (struct netdfs_add)); 161*5331Samw param->status = ERROR_ACCESS_DENIED; 162*5331Samw return (MLRPC_DRC_OK); 163*5331Samw } 164*5331Samw 165*5331Samw /* 166*5331Samw * netdfs_s_remove 167*5331Samw * 168*5331Samw * Remove a volume or additional storage for volume from the DFS at 169*5331Samw * dfs_path. When applied to the last storage in a volume, removes 170*5331Samw * the volume from the DFS. 171*5331Samw */ 172*5331Samw static int 173*5331Samw netdfs_s_remove(void *arg, struct mlrpc_xaction *mxa) 174*5331Samw { 175*5331Samw struct netdfs_remove *param = arg; 176*5331Samw netdfs_unc_t unc; 177*5331Samw DWORD status = ERROR_SUCCESS; 178*5331Samw 179*5331Samw if (param->dfs_path == NULL || param->server == NULL || 180*5331Samw param->share == NULL) { 181*5331Samw bzero(param, sizeof (struct netdfs_remove)); 182*5331Samw param->status = ERROR_INVALID_PARAMETER; 183*5331Samw return (MLRPC_DRC_OK); 184*5331Samw } 185*5331Samw 186*5331Samw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 187*5331Samw status = ERROR_INVALID_PARAMETER; 188*5331Samw } else { 189*5331Samw if (unc.path == NULL) 190*5331Samw status = ERROR_BAD_PATHNAME; 191*5331Samw 192*5331Samw if (unc.share == NULL) 193*5331Samw status = ERROR_INVALID_SHARENAME; 194*5331Samw } 195*5331Samw 196*5331Samw if (param->status != ERROR_SUCCESS) { 197*5331Samw bzero(param, sizeof (struct netdfs_remove)); 198*5331Samw param->status = status; 199*5331Samw return (MLRPC_DRC_OK); 200*5331Samw } 201*5331Samw 202*5331Samw bzero(param, sizeof (struct netdfs_remove)); 203*5331Samw param->status = ERROR_ACCESS_DENIED; 204*5331Samw return (MLRPC_DRC_OK); 205*5331Samw } 206*5331Samw 207*5331Samw /* 208*5331Samw * Set information about the volume or storage. If the server and share 209*5331Samw * are specified, the information set is specific to that server and 210*5331Samw * share. Otherwise the information is specific to the volume as a whole. 211*5331Samw * 212*5331Samw * Valid levels are 100-102. 213*5331Samw */ 214*5331Samw /*ARGSUSED*/ 215*5331Samw static int 216*5331Samw netdfs_s_setinfo(void *arg, struct mlrpc_xaction *mxa) 217*5331Samw { 218*5331Samw struct netdfs_setinfo *param = arg; 219*5331Samw netdfs_unc_t unc; 220*5331Samw DWORD status = ERROR_SUCCESS; 221*5331Samw 222*5331Samw if (param->dfs_path == NULL) { 223*5331Samw bzero(param, sizeof (struct netdfs_setinfo)); 224*5331Samw param->status = ERROR_INVALID_PARAMETER; 225*5331Samw return (MLRPC_DRC_OK); 226*5331Samw } 227*5331Samw 228*5331Samw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 229*5331Samw status = ERROR_INVALID_PARAMETER; 230*5331Samw } else { 231*5331Samw if (unc.share == NULL) 232*5331Samw status = ERROR_INVALID_SHARENAME; 233*5331Samw } 234*5331Samw 235*5331Samw if (param->status != ERROR_SUCCESS) { 236*5331Samw bzero(param, sizeof (struct netdfs_setinfo)); 237*5331Samw param->status = status; 238*5331Samw return (MLRPC_DRC_OK); 239*5331Samw } 240*5331Samw 241*5331Samw switch (param->info.level) { 242*5331Samw case 100: 243*5331Samw case 101: 244*5331Samw case 102: 245*5331Samw break; 246*5331Samw 247*5331Samw default: 248*5331Samw bzero(param, sizeof (struct netdfs_setinfo)); 249*5331Samw param->status = ERROR_INVALID_LEVEL; 250*5331Samw return (MLRPC_DRC_OK); 251*5331Samw } 252*5331Samw 253*5331Samw bzero(param, sizeof (struct netdfs_setinfo)); 254*5331Samw param->status = ERROR_ACCESS_DENIED; 255*5331Samw return (MLRPC_DRC_OK); 256*5331Samw } 257*5331Samw 258*5331Samw /* 259*5331Samw * Get information about the volume or storage. If the server and share 260*5331Samw * are specified, the information returned is specific to that server 261*5331Samw * and share. Otherwise the information is specific to the volume as a 262*5331Samw * whole. 263*5331Samw * 264*5331Samw * Valid levels are 1-4, 100-104. 265*5331Samw */ 266*5331Samw /*ARGSUSED*/ 267*5331Samw static int 268*5331Samw netdfs_s_getinfo(void *arg, struct mlrpc_xaction *mxa) 269*5331Samw { 270*5331Samw struct netdfs_getinfo *param = arg; 271*5331Samw netdfs_unc_t unc; 272*5331Samw DWORD status = ERROR_SUCCESS; 273*5331Samw 274*5331Samw if (param->dfs_path == NULL) { 275*5331Samw bzero(param, sizeof (struct netdfs_getinfo)); 276*5331Samw param->status = ERROR_INVALID_PARAMETER; 277*5331Samw return (MLRPC_DRC_OK); 278*5331Samw } 279*5331Samw 280*5331Samw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 281*5331Samw status = ERROR_INVALID_PARAMETER; 282*5331Samw } else { 283*5331Samw if (unc.share == NULL) 284*5331Samw status = ERROR_INVALID_SHARENAME; 285*5331Samw } 286*5331Samw 287*5331Samw if (param->status != ERROR_SUCCESS) { 288*5331Samw bzero(param, sizeof (struct netdfs_getinfo)); 289*5331Samw param->status = status; 290*5331Samw return (MLRPC_DRC_OK); 291*5331Samw } 292*5331Samw 293*5331Samw switch (param->level) { 294*5331Samw case 1: 295*5331Samw case 2: 296*5331Samw case 3: 297*5331Samw case 4: 298*5331Samw case 100: 299*5331Samw case 101: 300*5331Samw case 102: 301*5331Samw case 103: 302*5331Samw case 104: 303*5331Samw break; 304*5331Samw 305*5331Samw default: 306*5331Samw bzero(param, sizeof (struct netdfs_getinfo)); 307*5331Samw param->status = ERROR_INVALID_LEVEL; 308*5331Samw return (MLRPC_DRC_OK); 309*5331Samw } 310*5331Samw 311*5331Samw bzero(param, sizeof (struct netdfs_getinfo)); 312*5331Samw param->status = ERROR_ACCESS_DENIED; 313*5331Samw return (MLRPC_DRC_OK); 314*5331Samw } 315*5331Samw 316*5331Samw /* 317*5331Samw * Get information about all of the volumes in the DFS. dfs_name is 318*5331Samw * the "server" part of the UNC name used to refer to this particular 319*5331Samw * DFS. 320*5331Samw * 321*5331Samw * Valid levels are 1-3. 322*5331Samw */ 323*5331Samw /*ARGSUSED*/ 324*5331Samw static int 325*5331Samw netdfs_s_enum(void *arg, struct mlrpc_xaction *mxa) 326*5331Samw { 327*5331Samw struct netdfs_enum *param = arg; 328*5331Samw 329*5331Samw switch (param->level) { 330*5331Samw case 1: 331*5331Samw case 2: 332*5331Samw case 3: 333*5331Samw break; 334*5331Samw 335*5331Samw default: 336*5331Samw (void) bzero(param, sizeof (struct netdfs_enum)); 337*5331Samw param->status = ERROR_INVALID_LEVEL; 338*5331Samw return (MLRPC_DRC_OK); 339*5331Samw } 340*5331Samw 341*5331Samw (void) bzero(param, sizeof (struct netdfs_enum)); 342*5331Samw param->status = ERROR_ACCESS_DENIED; 343*5331Samw return (MLRPC_DRC_OK); 344*5331Samw } 345*5331Samw 346*5331Samw /* 347*5331Samw * Move a DFS volume and all subordinate volumes from one place in the 348*5331Samw * DFS to another place in the DFS. 349*5331Samw */ 350*5331Samw /*ARGSUSED*/ 351*5331Samw static int 352*5331Samw netdfs_s_move(void *arg, struct mlrpc_xaction *mxa) 353*5331Samw { 354*5331Samw struct netdfs_move *param = arg; 355*5331Samw 356*5331Samw if (param->dfs_path == NULL || param->new_path == NULL) { 357*5331Samw bzero(param, sizeof (struct netdfs_move)); 358*5331Samw param->status = ERROR_INVALID_PARAMETER; 359*5331Samw return (MLRPC_DRC_OK); 360*5331Samw } 361*5331Samw 362*5331Samw bzero(param, sizeof (struct netdfs_move)); 363*5331Samw param->status = ERROR_ACCESS_DENIED; 364*5331Samw return (MLRPC_DRC_OK); 365*5331Samw } 366*5331Samw 367*5331Samw /* 368*5331Samw * Rename the current path in a DFS to a new path in the same DFS. 369*5331Samw */ 370*5331Samw /*ARGSUSED*/ 371*5331Samw static int 372*5331Samw netdfs_s_rename(void *arg, struct mlrpc_xaction *mxa) 373*5331Samw { 374*5331Samw struct netdfs_rename *param = arg; 375*5331Samw 376*5331Samw if (param->dfs_path == NULL || param->new_path == NULL) { 377*5331Samw bzero(param, sizeof (struct netdfs_rename)); 378*5331Samw param->status = ERROR_INVALID_PARAMETER; 379*5331Samw return (MLRPC_DRC_OK); 380*5331Samw } 381*5331Samw 382*5331Samw bzero(param, sizeof (struct netdfs_rename)); 383*5331Samw param->status = ERROR_ACCESS_DENIED; 384*5331Samw return (MLRPC_DRC_OK); 385*5331Samw } 386*5331Samw 387*5331Samw /* 388*5331Samw * Add a DFS root share. 389*5331Samw */ 390*5331Samw /*ARGSUSED*/ 391*5331Samw static int 392*5331Samw netdfs_s_addstdroot(void *arg, struct mlrpc_xaction *mxa) 393*5331Samw { 394*5331Samw struct netdfs_addstdroot *param = arg; 395*5331Samw 396*5331Samw bzero(param, sizeof (struct netdfs_addstdroot)); 397*5331Samw param->status = ERROR_INVALID_PARAMETER; 398*5331Samw return (MLRPC_DRC_OK); 399*5331Samw } 400*5331Samw 401*5331Samw /* 402*5331Samw * Remove a DFS root share. 403*5331Samw */ 404*5331Samw /*ARGSUSED*/ 405*5331Samw static int 406*5331Samw netdfs_s_remstdroot(void *arg, struct mlrpc_xaction *mxa) 407*5331Samw { 408*5331Samw struct netdfs_remstdroot *param = arg; 409*5331Samw 410*5331Samw bzero(param, sizeof (struct netdfs_remstdroot)); 411*5331Samw param->status = ERROR_INVALID_PARAMETER; 412*5331Samw return (MLRPC_DRC_OK); 413*5331Samw } 414*5331Samw 415*5331Samw /* 416*5331Samw * Get information about all of the volumes in the DFS. dfs_path is 417*5331Samw * the "server" part of the UNC name used to refer to this particular 418*5331Samw * DFS. 419*5331Samw * 420*5331Samw * Valid levels are 1-3, 300. 421*5331Samw */ 422*5331Samw static int 423*5331Samw netdfs_s_enumex(void *arg, struct mlrpc_xaction *mxa) 424*5331Samw { 425*5331Samw struct netdfs_enumex *param = arg; 426*5331Samw netdfs_unc_t unc; 427*5331Samw DWORD status = ERROR_SUCCESS; 428*5331Samw 429*5331Samw if (param->dfs_path == NULL) { 430*5331Samw bzero(param, sizeof (struct netdfs_enumex)); 431*5331Samw param->status = ERROR_INVALID_PARAMETER; 432*5331Samw return (MLRPC_DRC_OK); 433*5331Samw } 434*5331Samw 435*5331Samw if (param->resume_handle == NULL) 436*5331Samw param->resume_handle = MLRPC_HEAP_NEW(mxa, DWORD); 437*5331Samw 438*5331Samw if (param->resume_handle) 439*5331Samw *(param->resume_handle) = 0; 440*5331Samw 441*5331Samw if (netdfs_unc_parse(mxa, (char *)param->dfs_path, &unc) != 0) { 442*5331Samw status = ERROR_INVALID_PARAMETER; 443*5331Samw } else { 444*5331Samw if (unc.path == NULL) 445*5331Samw status = ERROR_BAD_PATHNAME; 446*5331Samw 447*5331Samw if (unc.share == NULL) 448*5331Samw status = ERROR_INVALID_SHARENAME; 449*5331Samw } 450*5331Samw 451*5331Samw if (param->status != ERROR_SUCCESS) { 452*5331Samw bzero(param, sizeof (struct netdfs_enumex)); 453*5331Samw param->status = status; 454*5331Samw return (MLRPC_DRC_OK); 455*5331Samw } 456*5331Samw 457*5331Samw param->info = MLRPC_HEAP_NEW(mxa, struct netdfs_enum_info); 458*5331Samw if (param->info == NULL) { 459*5331Samw bzero(param, sizeof (struct netdfs_enumex)); 460*5331Samw param->status = ERROR_NOT_ENOUGH_MEMORY; 461*5331Samw return (MLRPC_DRC_OK); 462*5331Samw } 463*5331Samw 464*5331Samw bzero(param->info, sizeof (struct netdfs_enumex)); 465*5331Samw param->status = ERROR_SUCCESS; 466*5331Samw return (MLRPC_DRC_OK); 467*5331Samw } 468*5331Samw 469*5331Samw /* 470*5331Samw * Parse a UNC path (\\server\share\path) into components. 471*5331Samw * Path separators are converted to forward slashes. 472*5331Samw * 473*5331Samw * Returns 0 on success, otherwise -1 to indicate an error. 474*5331Samw */ 475*5331Samw static int 476*5331Samw netdfs_unc_parse(struct mlrpc_xaction *mxa, const char *path, netdfs_unc_t *unc) 477*5331Samw { 478*5331Samw char *p; 479*5331Samw 480*5331Samw if (path == NULL || unc == NULL) 481*5331Samw return (-1); 482*5331Samw 483*5331Samw if ((unc->buf = MLRPC_HEAP_STRSAVE(mxa, (char *)path)) == NULL) 484*5331Samw return (-1); 485*5331Samw 486*5331Samw if ((p = strchr(unc->buf, '\n')) != NULL) 487*5331Samw *p = '\0'; 488*5331Samw 489*5331Samw (void) strsubst(unc->buf, '\\', '/'); 490*5331Samw (void) strcanon(unc->buf, "/"); 491*5331Samw 492*5331Samw unc->server = unc->buf; 493*5331Samw unc->server += strspn(unc->buf, "/"); 494*5331Samw 495*5331Samw if (unc->server) { 496*5331Samw unc->share = strchr(unc->server, '/'); 497*5331Samw if ((p = unc->share) != NULL) { 498*5331Samw unc->share += strspn(unc->share, "/"); 499*5331Samw *p = '\0'; 500*5331Samw } 501*5331Samw } 502*5331Samw 503*5331Samw if (unc->share) { 504*5331Samw unc->path = strchr(unc->share, '/'); 505*5331Samw if ((p = unc->path) != NULL) { 506*5331Samw unc->path += strspn(unc->path, "/"); 507*5331Samw *p = '\0'; 508*5331Samw } 509*5331Samw } 510*5331Samw 511*5331Samw if (unc->path) { 512*5331Samw if ((p = strchr(unc->path, '\0')) != NULL) { 513*5331Samw if (*(--p) == '/') 514*5331Samw *p = '\0'; 515*5331Samw } 516*5331Samw } 517*5331Samw 518*5331Samw return (0); 519*5331Samw } 520