1/* 2 * Unix SMB/CIFS implementation. 3 * RPC Pipe client / server routines 4 * 5 * Copyright (C) Andrew Tridgell 1992-1997, 6 * Copyright (C) Gerald (Jerry) Carter 2006. 7 * Copyright (C) Guenther Deschner 2007-2008. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, see <http://www.gnu.org/licenses/>. 21 */ 22 23/* This is the implementation of the wks interface. */ 24 25#include "includes.h" 26#include "libnet/libnet.h" 27#include "../libcli/auth/libcli_auth.h" 28#include "../librpc/gen_ndr/srv_wkssvc.h" 29 30#undef DBGC_CLASS 31#define DBGC_CLASS DBGC_RPC_SRV 32 33struct dom_usr { 34 char *name; 35 char *domain; 36 time_t login_time; 37}; 38 39#ifdef HAVE_GETUTXENT 40 41#include <utmpx.h> 42 43struct usrinfo { 44 char *name; 45 struct timeval login_time; 46}; 47 48static int usr_info_cmp(const void *p1, const void *p2) 49{ 50 const struct usrinfo *usr1 = (const struct usrinfo *)p1; 51 const struct usrinfo *usr2 = (const struct usrinfo *)p2; 52 53 /* Called from qsort to compare two users in a usrinfo_t array for 54 * sorting by login time. Return >0 if usr1 login time was later than 55 * usr2 login time, <0 if it was earlier */ 56 return timeval_compare(&usr1->login_time, &usr2->login_time); 57} 58 59/******************************************************************* 60 Get a list of the names of all users logged into this machine 61 ********************************************************************/ 62 63static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx) 64{ 65 char **users; 66 int i, num_users = 0; 67 struct usrinfo *usr_infos = NULL; 68 struct utmpx *u; 69 70 while ((u = getutxent()) != NULL) { 71 struct usrinfo *tmp; 72 if (u->ut_type != USER_PROCESS) { 73 continue; 74 } 75 for (i = 0; i < num_users; i++) { 76 /* getutxent can return multiple user entries for the 77 * same user, so ignore any dups */ 78 if (strcmp(u->ut_user, usr_infos[i].name) == 0) { 79 break; 80 } 81 } 82 if (i < num_users) { 83 continue; 84 } 85 86 tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo, 87 num_users+1); 88 if (tmp == NULL) { 89 TALLOC_FREE(tmp); 90 endutxent(); 91 return NULL; 92 } 93 usr_infos = tmp; 94 usr_infos[num_users].name = talloc_strdup(usr_infos, 95 u->ut_user); 96 if (usr_infos[num_users].name == NULL) { 97 TALLOC_FREE(usr_infos); 98 endutxent(); 99 return NULL; 100 } 101 usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec; 102 usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec; 103 num_users += 1; 104 } 105 106 /* Sort the user list by time, oldest first */ 107 qsort(usr_infos, num_users, sizeof(struct usrinfo), usr_info_cmp); 108 109 users = (char**)talloc_array(mem_ctx, char*, num_users); 110 if (users) { 111 for (i = 0; i < num_users; i++) { 112 users[i] = talloc_move(users, &usr_infos[i].name); 113 } 114 } 115 TALLOC_FREE(usr_infos); 116 endutxent(); 117 errno = 0; 118 return users; 119} 120 121#else 122 123static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx) 124{ 125 return NULL; 126} 127 128#endif 129 130static int dom_user_cmp(const void *p1, const void *p2) 131{ 132 /* Called from qsort to compare two domain users in a dom_usr_t array 133 * for sorting by login time. Return >0 if usr1 login time was later 134 * than usr2 login time, <0 if it was earlier */ 135 const struct dom_usr *usr1 = (const struct dom_usr *)p1; 136 const struct dom_usr *usr2 = (const struct dom_usr *)p2; 137 138 return (usr1->login_time - usr2->login_time); 139} 140 141/******************************************************************* 142 Get a list of the names of all users of this machine who are 143 logged into the domain. 144 145 This should return a list of the users on this machine who are 146 logged into the domain (i.e. have been authenticated by the domain's 147 password server) but that doesn't fit well with the normal Samba 148 scenario where accesses out to the domain are made through smbclient 149 with each such session individually authenticated. So about the best 150 we can do currently is to list sessions of local users connected to 151 this server, which means that to get themself included in the list a 152 local user must create a session to the local samba server by running: 153 smbclient \\\\localhost\\share 154 155 FIXME: find a better way to get local users logged into the domain 156 in this list. 157 ********************************************************************/ 158 159static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx) 160{ 161 struct sessionid *session_list = NULL; 162 char *machine_name, *p, *nm; 163 const char *sep; 164 struct dom_usr *users, *tmp; 165 int i, num_users, num_sessions; 166 167 sep = lp_winbind_separator(); 168 if (!sep) { 169 sep = "\\"; 170 } 171 172 num_sessions = list_sessions(mem_ctx, &session_list); 173 if (num_sessions == 0) { 174 errno = 0; 175 return NULL; 176 } 177 178 users = talloc_array(mem_ctx, struct dom_usr, num_sessions); 179 if (users == NULL) { 180 TALLOC_FREE(session_list); 181 return NULL; 182 } 183 184 for (i=num_users=0; i<num_sessions; i++) { 185 if (!session_list[i].username 186 || !session_list[i].remote_machine) { 187 continue; 188 } 189 p = strpbrk(session_list[i].remote_machine, "./"); 190 if (p) { 191 *p = '\0'; 192 } 193 machine_name = talloc_asprintf_strupper_m( 194 users, "%s", session_list[i].remote_machine); 195 if (machine_name == NULL) { 196 DEBUG(10, ("talloc_asprintf failed\n")); 197 continue; 198 } 199 if (strcmp(machine_name, global_myname()) == 0) { 200 p = session_list[i].username; 201 nm = strstr(p, sep); 202 if (nm) { 203 /* 204 * "domain+name" format so split domain and 205 * name components 206 */ 207 *nm = '\0'; 208 nm += strlen(sep); 209 users[num_users].domain = 210 talloc_asprintf_strupper_m(users, 211 "%s", p); 212 users[num_users].name = talloc_strdup(users, 213 nm); 214 } else { 215 /* 216 * Simple user name so get domain from smb.conf 217 */ 218 users[num_users].domain = 219 talloc_strdup(users, lp_workgroup()); 220 users[num_users].name = talloc_strdup(users, 221 p); 222 } 223 users[num_users].login_time = 224 session_list[i].connect_start; 225 num_users++; 226 } 227 TALLOC_FREE(machine_name); 228 } 229 TALLOC_FREE(session_list); 230 231 tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users); 232 if (tmp == NULL) { 233 return NULL; 234 } 235 users = tmp; 236 237 /* Sort the user list by time, oldest first */ 238 qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp); 239 240 errno = 0; 241 return users; 242} 243 244/******************************************************************* 245 RPC Workstation Service request NetWkstaGetInfo with level 100. 246 Returns to the requester: 247 - The machine name. 248 - The smb version number 249 - The domain name. 250 Returns a filled in wkssvc_NetWkstaInfo100 struct. 251 ********************************************************************/ 252 253static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx) 254{ 255 struct wkssvc_NetWkstaInfo100 *info100; 256 257 info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100); 258 if (info100 == NULL) { 259 return NULL; 260 } 261 262 info100->platform_id = PLATFORM_ID_NT; /* unknown */ 263 info100->version_major = lp_major_announce_version(); 264 info100->version_minor = lp_minor_announce_version(); 265 266 info100->server_name = talloc_asprintf_strupper_m( 267 info100, "%s", global_myname()); 268 info100->domain_name = talloc_asprintf_strupper_m( 269 info100, "%s", lp_workgroup()); 270 271 return info100; 272} 273 274/******************************************************************* 275 RPC Workstation Service request NetWkstaGetInfo with level 101. 276 Returns to the requester: 277 - As per NetWkstaGetInfo with level 100, plus: 278 - The LANMAN directory path (not currently supported). 279 Returns a filled in wkssvc_NetWkstaInfo101 struct. 280 ********************************************************************/ 281 282static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx) 283{ 284 struct wkssvc_NetWkstaInfo101 *info101; 285 286 info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101); 287 if (info101 == NULL) { 288 return NULL; 289 } 290 291 info101->platform_id = PLATFORM_ID_NT; /* unknown */ 292 info101->version_major = lp_major_announce_version(); 293 info101->version_minor = lp_minor_announce_version(); 294 295 info101->server_name = talloc_asprintf_strupper_m( 296 info101, "%s", global_myname()); 297 info101->domain_name = talloc_asprintf_strupper_m( 298 info101, "%s", lp_workgroup()); 299 info101->lan_root = ""; 300 301 return info101; 302} 303 304/******************************************************************* 305 RPC Workstation Service request NetWkstaGetInfo with level 102. 306 Returns to the requester: 307 - As per NetWkstaGetInfo with level 101, plus: 308 - The number of logged in users. 309 Returns a filled in wkssvc_NetWkstaInfo102 struct. 310 ********************************************************************/ 311 312static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx) 313{ 314 struct wkssvc_NetWkstaInfo102 *info102; 315 char **users; 316 317 info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102); 318 if (info102 == NULL) { 319 return NULL; 320 } 321 322 info102->platform_id = PLATFORM_ID_NT; /* unknown */ 323 info102->version_major = lp_major_announce_version(); 324 info102->version_minor = lp_minor_announce_version(); 325 326 info102->server_name = talloc_asprintf_strupper_m( 327 info102, "%s", global_myname()); 328 info102->domain_name = talloc_asprintf_strupper_m( 329 info102, "%s", lp_workgroup()); 330 info102->lan_root = ""; 331 332 users = get_logged_on_userlist(talloc_tos()); 333 info102->logged_on_users = talloc_array_length(users); 334 335 TALLOC_FREE(users); 336 337 return info102; 338} 339 340/******************************************************************** 341 Handling for RPC Workstation Service request NetWkstaGetInfo 342 ********************************************************************/ 343 344WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r) 345{ 346 switch (r->in.level) { 347 case 100: 348 /* Level 100 can be allowed from anyone including anonymous 349 * so no access checks are needed for this case */ 350 r->out.info->info100 = create_wks_info_100(p->mem_ctx); 351 if (r->out.info->info100 == NULL) { 352 return WERR_NOMEM; 353 } 354 break; 355 case 101: 356 /* Level 101 can be allowed from any logged in user */ 357 if (!nt_token_check_sid(&global_sid_Authenticated_Users, 358 p->server_info->ptok)) { 359 DEBUG(1,("User not allowed for NetWkstaGetInfo level " 360 "101\n")); 361 DEBUGADD(3,(" - does not have sid for Authenticated " 362 "Users %s:\n", 363 sid_string_dbg( 364 &global_sid_Authenticated_Users))); 365 debug_nt_user_token(DBGC_CLASS, 3, 366 p->server_info->ptok); 367 return WERR_ACCESS_DENIED; 368 } 369 r->out.info->info101 = create_wks_info_101(p->mem_ctx); 370 if (r->out.info->info101 == NULL) { 371 return WERR_NOMEM; 372 } 373 break; 374 case 102: 375 /* Level 102 Should only be allowed from a domain administrator */ 376 if (!nt_token_check_sid(&global_sid_Builtin_Administrators, 377 p->server_info->ptok)) { 378 DEBUG(1,("User not allowed for NetWkstaGetInfo level " 379 "102\n")); 380 DEBUGADD(3,(" - does not have sid for Administrators " 381 "group %s, sids are:\n", 382 sid_string_dbg(&global_sid_Builtin_Administrators))); 383 debug_nt_user_token(DBGC_CLASS, 3, 384 p->server_info->ptok); 385 return WERR_ACCESS_DENIED; 386 } 387 r->out.info->info102 = create_wks_info_102(p->mem_ctx); 388 if (r->out.info->info102 == NULL) { 389 return WERR_NOMEM; 390 } 391 break; 392 default: 393 return WERR_UNKNOWN_LEVEL; 394 } 395 396 return WERR_OK; 397} 398 399/******************************************************************** 400 ********************************************************************/ 401 402WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r) 403{ 404 /* FIXME: Add implementation code here */ 405 p->rng_fault_state = True; 406 return WERR_NOT_SUPPORTED; 407} 408 409/******************************************************************** 410 RPC Workstation Service request NetWkstaEnumUsers with level 0: 411 Returns to the requester: 412 - the user names of the logged in users. 413 Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct. 414 ********************************************************************/ 415 416static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0( 417 TALLOC_CTX *mem_ctx) 418{ 419 struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0; 420 char **users; 421 int i, num_users; 422 423 ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0); 424 if (ctr0 == NULL) { 425 return NULL; 426 } 427 428 users = get_logged_on_userlist(talloc_tos()); 429 if (users == NULL && errno != 0) { 430 DEBUG(1,("get_logged_on_userlist error %d: %s\n", 431 errno, strerror(errno))); 432 TALLOC_FREE(ctr0); 433 return NULL; 434 } 435 436 num_users = talloc_array_length(users); 437 ctr0->entries_read = num_users; 438 ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0, 439 num_users); 440 if (ctr0->user0 == NULL) { 441 TALLOC_FREE(ctr0); 442 TALLOC_FREE(users); 443 return NULL; 444 } 445 446 for (i=0; i<num_users; i++) { 447 ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]); 448 } 449 TALLOC_FREE(users); 450 return ctr0; 451} 452 453/******************************************************************** 454 RPC Workstation Service request NetWkstaEnumUsers with level 1. 455 Returns to the requester: 456 - the user names of the logged in users, 457 - the domain or machine each is logged into, 458 - the password server that was used to authenticate each, 459 - other domains each user is logged into (not currently supported). 460 Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct. 461 ********************************************************************/ 462 463static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1( 464 TALLOC_CTX *mem_ctx) 465{ 466 struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1; 467 char **users; 468 struct dom_usr *dom_users; 469 const char *pwd_server; 470 char *pwd_tmp; 471 int i, j, num_users, num_dom_users; 472 473 ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1); 474 if (ctr1 == NULL) { 475 return NULL; 476 } 477 478 users = get_logged_on_userlist(talloc_tos()); 479 if (users == NULL && errno != 0) { 480 DEBUG(1,("get_logged_on_userlist error %d: %s\n", 481 errno, strerror(errno))); 482 TALLOC_FREE(ctr1); 483 return NULL; 484 } 485 num_users = talloc_array_length(users); 486 487 dom_users = get_domain_userlist(talloc_tos()); 488 if (dom_users == NULL && errno != 0) { 489 TALLOC_FREE(ctr1); 490 TALLOC_FREE(users); 491 return NULL; 492 } 493 num_dom_users = talloc_array_length(dom_users); 494 495 ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1, 496 num_users+num_dom_users); 497 if (ctr1->user1 == NULL) { 498 TALLOC_FREE(ctr1); 499 TALLOC_FREE(users); 500 TALLOC_FREE(dom_users); 501 return NULL; 502 } 503 504 pwd_server = ""; 505 506 if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) { 507 /* The configured password server is a full DNS name but 508 * for the logon server we need to return just the first 509 * component (machine name) of it in upper-case */ 510 char *p = strchr(pwd_tmp, '.'); 511 if (p) { 512 *p = '\0'; 513 } else { 514 p = pwd_tmp + strlen(pwd_tmp); 515 } 516 while (--p >= pwd_tmp) { 517 *p = toupper(*p); 518 } 519 pwd_server = pwd_tmp; 520 } 521 522 /* Put in local users first */ 523 for (i=0; i<num_users; i++) { 524 ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]); 525 526 /* For a local user the domain name and logon server are 527 * both returned as the local machine's NetBIOS name */ 528 ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server = 529 talloc_asprintf_strupper_m(ctr1->user1, "%s", global_myname()); 530 531 ctr1->user1[i].other_domains = NULL; /* Maybe in future? */ 532 } 533 534 /* Now domain users */ 535 for (j=0; j<num_dom_users; j++) { 536 ctr1->user1[i].user_name = 537 talloc_strdup(ctr1->user1, dom_users[j].name); 538 ctr1->user1[i].logon_domain = 539 talloc_strdup(ctr1->user1, dom_users[j].domain); 540 ctr1->user1[i].logon_server = pwd_server; 541 542 ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */ 543 } 544 545 ctr1->entries_read = i; 546 547 TALLOC_FREE(users); 548 TALLOC_FREE(dom_users); 549 return ctr1; 550} 551 552/******************************************************************** 553 Handling for RPC Workstation Service request NetWkstaEnumUsers 554 (a.k.a Windows NetWkstaUserEnum) 555 ********************************************************************/ 556 557WERROR _wkssvc_NetWkstaEnumUsers(pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r) 558{ 559 /* This with any level should only be allowed from a domain administrator */ 560 if (!nt_token_check_sid(&global_sid_Builtin_Administrators, 561 p->server_info->ptok)) { 562 DEBUG(1,("User not allowed for NetWkstaEnumUsers\n")); 563 DEBUGADD(3,(" - does not have sid for Administrators group " 564 "%s\n", sid_string_dbg( 565 &global_sid_Builtin_Administrators))); 566 debug_nt_user_token(DBGC_CLASS, 3, p->server_info->ptok); 567 return WERR_ACCESS_DENIED; 568 } 569 570 switch (r->in.info->level) { 571 case 0: 572 r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx); 573 if (r->out.info->ctr.user0 == NULL) { 574 return WERR_NOMEM; 575 } 576 r->out.info->level = r->in.info->level; 577 *r->out.entries_read = r->out.info->ctr.user0->entries_read; 578 *r->out.resume_handle = 0; 579 break; 580 case 1: 581 r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx); 582 if (r->out.info->ctr.user1 == NULL) { 583 return WERR_NOMEM; 584 } 585 r->out.info->level = r->in.info->level; 586 *r->out.entries_read = r->out.info->ctr.user1->entries_read; 587 *r->out.resume_handle = 0; 588 break; 589 default: 590 return WERR_UNKNOWN_LEVEL; 591 } 592 593 return WERR_OK; 594} 595 596/******************************************************************** 597 ********************************************************************/ 598 599WERROR _wkssvc_NetrWkstaUserGetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserGetInfo *r) 600{ 601 /* FIXME: Add implementation code here */ 602 p->rng_fault_state = True; 603 return WERR_NOT_SUPPORTED; 604} 605 606/******************************************************************** 607 ********************************************************************/ 608 609WERROR _wkssvc_NetrWkstaUserSetInfo(pipes_struct *p, struct wkssvc_NetrWkstaUserSetInfo *r) 610{ 611 /* FIXME: Add implementation code here */ 612 p->rng_fault_state = True; 613 return WERR_NOT_SUPPORTED; 614} 615 616/******************************************************************** 617 ********************************************************************/ 618 619WERROR _wkssvc_NetWkstaTransportEnum(pipes_struct *p, struct wkssvc_NetWkstaTransportEnum *r) 620{ 621 /* FIXME: Add implementation code here */ 622 p->rng_fault_state = True; 623 return WERR_NOT_SUPPORTED; 624} 625 626/******************************************************************** 627 ********************************************************************/ 628 629WERROR _wkssvc_NetrWkstaTransportAdd(pipes_struct *p, struct wkssvc_NetrWkstaTransportAdd *r) 630{ 631 /* FIXME: Add implementation code here */ 632 p->rng_fault_state = True; 633 return WERR_NOT_SUPPORTED; 634} 635 636/******************************************************************** 637 ********************************************************************/ 638 639WERROR _wkssvc_NetrWkstaTransportDel(pipes_struct *p, struct wkssvc_NetrWkstaTransportDel *r) 640{ 641 /* FIXME: Add implementation code here */ 642 p->rng_fault_state = True; 643 return WERR_NOT_SUPPORTED; 644} 645 646/******************************************************************** 647 ********************************************************************/ 648 649WERROR _wkssvc_NetrUseAdd(pipes_struct *p, struct wkssvc_NetrUseAdd *r) 650{ 651 /* FIXME: Add implementation code here */ 652 p->rng_fault_state = True; 653 return WERR_NOT_SUPPORTED; 654} 655 656/******************************************************************** 657 ********************************************************************/ 658 659WERROR _wkssvc_NetrUseGetInfo(pipes_struct *p, struct wkssvc_NetrUseGetInfo *r) 660{ 661 /* FIXME: Add implementation code here */ 662 p->rng_fault_state = True; 663 return WERR_NOT_SUPPORTED; 664} 665 666/******************************************************************** 667 ********************************************************************/ 668 669WERROR _wkssvc_NetrUseDel(pipes_struct *p, struct wkssvc_NetrUseDel *r) 670{ 671 /* FIXME: Add implementation code here */ 672 p->rng_fault_state = True; 673 return WERR_NOT_SUPPORTED; 674} 675 676/******************************************************************** 677 ********************************************************************/ 678 679WERROR _wkssvc_NetrUseEnum(pipes_struct *p, struct wkssvc_NetrUseEnum *r) 680{ 681 /* FIXME: Add implementation code here */ 682 p->rng_fault_state = True; 683 return WERR_NOT_SUPPORTED; 684} 685 686/******************************************************************** 687 ********************************************************************/ 688 689WERROR _wkssvc_NetrMessageBufferSend(pipes_struct *p, struct wkssvc_NetrMessageBufferSend *r) 690{ 691 /* FIXME: Add implementation code here */ 692 p->rng_fault_state = True; 693 return WERR_NOT_SUPPORTED; 694} 695 696/******************************************************************** 697 ********************************************************************/ 698 699WERROR _wkssvc_NetrWorkstationStatisticsGet(pipes_struct *p, struct wkssvc_NetrWorkstationStatisticsGet *r) 700{ 701 /* FIXME: Add implementation code here */ 702 p->rng_fault_state = True; 703 return WERR_NOT_SUPPORTED; 704} 705 706/******************************************************************** 707 ********************************************************************/ 708 709WERROR _wkssvc_NetrLogonDomainNameAdd(pipes_struct *p, struct wkssvc_NetrLogonDomainNameAdd *r) 710{ 711 /* FIXME: Add implementation code here */ 712 p->rng_fault_state = True; 713 return WERR_NOT_SUPPORTED; 714} 715 716/******************************************************************** 717 ********************************************************************/ 718 719WERROR _wkssvc_NetrLogonDomainNameDel(pipes_struct *p, struct wkssvc_NetrLogonDomainNameDel *r) 720{ 721 /* FIXME: Add implementation code here */ 722 p->rng_fault_state = True; 723 return WERR_NOT_SUPPORTED; 724} 725 726/******************************************************************** 727 ********************************************************************/ 728 729WERROR _wkssvc_NetrJoinDomain(pipes_struct *p, struct wkssvc_NetrJoinDomain *r) 730{ 731 /* FIXME: Add implementation code here */ 732 p->rng_fault_state = True; 733 return WERR_NOT_SUPPORTED; 734} 735 736/******************************************************************** 737 ********************************************************************/ 738 739WERROR _wkssvc_NetrUnjoinDomain(pipes_struct *p, struct wkssvc_NetrUnjoinDomain *r) 740{ 741 /* FIXME: Add implementation code here */ 742 p->rng_fault_state = True; 743 return WERR_NOT_SUPPORTED; 744} 745 746/******************************************************************** 747 ********************************************************************/ 748 749WERROR _wkssvc_NetrRenameMachineInDomain(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain *r) 750{ 751 /* FIXME: Add implementation code here */ 752 p->rng_fault_state = True; 753 return WERR_NOT_SUPPORTED; 754} 755 756/******************************************************************** 757 ********************************************************************/ 758 759WERROR _wkssvc_NetrValidateName(pipes_struct *p, struct wkssvc_NetrValidateName *r) 760{ 761 /* FIXME: Add implementation code here */ 762 p->rng_fault_state = True; 763 return WERR_NOT_SUPPORTED; 764} 765 766/******************************************************************** 767 ********************************************************************/ 768 769WERROR _wkssvc_NetrGetJoinInformation(pipes_struct *p, struct wkssvc_NetrGetJoinInformation *r) 770{ 771 /* FIXME: Add implementation code here */ 772 p->rng_fault_state = True; 773 return WERR_NOT_SUPPORTED; 774} 775 776/******************************************************************** 777 ********************************************************************/ 778 779WERROR _wkssvc_NetrGetJoinableOus(pipes_struct *p, struct wkssvc_NetrGetJoinableOus *r) 780{ 781 /* FIXME: Add implementation code here */ 782 p->rng_fault_state = True; 783 return WERR_NOT_SUPPORTED; 784} 785 786/******************************************************************** 787 _wkssvc_NetrJoinDomain2 788 ********************************************************************/ 789 790WERROR _wkssvc_NetrJoinDomain2(pipes_struct *p, 791 struct wkssvc_NetrJoinDomain2 *r) 792{ 793 struct libnet_JoinCtx *j = NULL; 794 char *cleartext_pwd = NULL; 795 char *admin_domain = NULL; 796 char *admin_account = NULL; 797 WERROR werr; 798 struct nt_user_token *token = p->server_info->ptok; 799 800 if (!r->in.domain_name) { 801 return WERR_INVALID_PARAM; 802 } 803 804 if (!r->in.admin_account || !r->in.encrypted_password) { 805 return WERR_INVALID_PARAM; 806 } 807 808 if (!user_has_privileges(token, &se_machine_account) && 809 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) && 810 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) { 811 DEBUG(5,("_wkssvc_NetrJoinDomain2: account doesn't have " 812 "sufficient privileges\n")); 813 return WERR_ACCESS_DENIED; 814 } 815 816 if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED) || 817 (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) { 818 return WERR_NOT_SUPPORTED; 819 } 820 821 werr = decode_wkssvc_join_password_buffer( 822 p->mem_ctx, r->in.encrypted_password, 823 &p->server_info->user_session_key, &cleartext_pwd); 824 if (!W_ERROR_IS_OK(werr)) { 825 return werr; 826 } 827 828 split_domain_user(p->mem_ctx, 829 r->in.admin_account, 830 &admin_domain, 831 &admin_account); 832 833 werr = libnet_init_JoinCtx(p->mem_ctx, &j); 834 if (!W_ERROR_IS_OK(werr)) { 835 return werr; 836 } 837 838 j->in.domain_name = r->in.domain_name; 839 j->in.account_ou = r->in.account_ou; 840 j->in.join_flags = r->in.join_flags; 841 j->in.admin_account = admin_account; 842 j->in.admin_password = cleartext_pwd; 843 j->in.debug = true; 844 j->in.modify_config = lp_config_backend_is_registry(); 845 j->in.msg_ctx = smbd_messaging_context(); 846 847 become_root(); 848 werr = libnet_Join(p->mem_ctx, j); 849 unbecome_root(); 850 851 if (!W_ERROR_IS_OK(werr)) { 852 DEBUG(5,("_wkssvc_NetrJoinDomain2: libnet_Join failed with: %s\n", 853 j->out.error_string ? j->out.error_string : 854 win_errstr(werr))); 855 } 856 857 TALLOC_FREE(j); 858 return werr; 859} 860 861/******************************************************************** 862 _wkssvc_NetrUnjoinDomain2 863 ********************************************************************/ 864 865WERROR _wkssvc_NetrUnjoinDomain2(pipes_struct *p, 866 struct wkssvc_NetrUnjoinDomain2 *r) 867{ 868 struct libnet_UnjoinCtx *u = NULL; 869 char *cleartext_pwd = NULL; 870 char *admin_domain = NULL; 871 char *admin_account = NULL; 872 WERROR werr; 873 struct nt_user_token *token = p->server_info->ptok; 874 875 if (!r->in.account || !r->in.encrypted_password) { 876 return WERR_INVALID_PARAM; 877 } 878 879 if (!user_has_privileges(token, &se_machine_account) && 880 !nt_token_check_domain_rid(token, DOMAIN_GROUP_RID_ADMINS) && 881 !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) { 882 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have " 883 "sufficient privileges\n")); 884 return WERR_ACCESS_DENIED; 885 } 886 887 werr = decode_wkssvc_join_password_buffer( 888 p->mem_ctx, r->in.encrypted_password, 889 &p->server_info->user_session_key, &cleartext_pwd); 890 if (!W_ERROR_IS_OK(werr)) { 891 return werr; 892 } 893 894 split_domain_user(p->mem_ctx, 895 r->in.account, 896 &admin_domain, 897 &admin_account); 898 899 werr = libnet_init_UnjoinCtx(p->mem_ctx, &u); 900 if (!W_ERROR_IS_OK(werr)) { 901 return werr; 902 } 903 904 u->in.domain_name = lp_realm(); 905 u->in.unjoin_flags = r->in.unjoin_flags | 906 WKSSVC_JOIN_FLAGS_JOIN_TYPE; 907 u->in.admin_account = admin_account; 908 u->in.admin_password = cleartext_pwd; 909 u->in.debug = true; 910 u->in.modify_config = lp_config_backend_is_registry(); 911 u->in.msg_ctx = smbd_messaging_context(); 912 913 become_root(); 914 werr = libnet_Unjoin(p->mem_ctx, u); 915 unbecome_root(); 916 917 if (!W_ERROR_IS_OK(werr)) { 918 DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n", 919 u->out.error_string ? u->out.error_string : 920 win_errstr(werr))); 921 } 922 923 TALLOC_FREE(u); 924 return werr; 925} 926 927/******************************************************************** 928 ********************************************************************/ 929 930WERROR _wkssvc_NetrRenameMachineInDomain2(pipes_struct *p, struct wkssvc_NetrRenameMachineInDomain2 *r) 931{ 932 /* for now just return not supported */ 933 return WERR_NOT_SUPPORTED; 934} 935 936/******************************************************************** 937 ********************************************************************/ 938 939WERROR _wkssvc_NetrValidateName2(pipes_struct *p, struct wkssvc_NetrValidateName2 *r) 940{ 941 /* FIXME: Add implementation code here */ 942 p->rng_fault_state = True; 943 return WERR_NOT_SUPPORTED; 944} 945 946/******************************************************************** 947 ********************************************************************/ 948 949WERROR _wkssvc_NetrGetJoinableOus2(pipes_struct *p, struct wkssvc_NetrGetJoinableOus2 *r) 950{ 951 /* FIXME: Add implementation code here */ 952 p->rng_fault_state = True; 953 return WERR_NOT_SUPPORTED; 954} 955 956/******************************************************************** 957 ********************************************************************/ 958 959WERROR _wkssvc_NetrAddAlternateComputerName(pipes_struct *p, struct wkssvc_NetrAddAlternateComputerName *r) 960{ 961 /* FIXME: Add implementation code here */ 962 p->rng_fault_state = True; 963 return WERR_NOT_SUPPORTED; 964} 965 966/******************************************************************** 967 ********************************************************************/ 968 969WERROR _wkssvc_NetrRemoveAlternateComputerName(pipes_struct *p, struct wkssvc_NetrRemoveAlternateComputerName *r) 970{ 971 /* FIXME: Add implementation code here */ 972 p->rng_fault_state = True; 973 return WERR_NOT_SUPPORTED; 974} 975 976/******************************************************************** 977 ********************************************************************/ 978 979WERROR _wkssvc_NetrSetPrimaryComputername(pipes_struct *p, struct wkssvc_NetrSetPrimaryComputername *r) 980{ 981 /* FIXME: Add implementation code here */ 982 p->rng_fault_state = True; 983 return WERR_NOT_SUPPORTED; 984} 985 986/******************************************************************** 987 ********************************************************************/ 988 989WERROR _wkssvc_NetrEnumerateComputerNames(pipes_struct *p, struct wkssvc_NetrEnumerateComputerNames *r) 990{ 991 /* FIXME: Add implementation code here */ 992 p->rng_fault_state = True; 993 return WERR_NOT_SUPPORTED; 994} 995 996