1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21*148c5f43SAlan Wright 22da6c28aaSamw /* 23*148c5f43SAlan Wright * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * Server Service (srvsvc) client side RPC library interface. The 28da6c28aaSamw * srvsvc interface allows a client to query a server for information 29da6c28aaSamw * on shares, sessions, connections and files on the server. Some 30da6c28aaSamw * functions are available via anonymous IPC while others require 31da6c28aaSamw * administrator privilege. Also, some functions return NT status 32da6c28aaSamw * values while others return Win32 errors codes. 33da6c28aaSamw */ 34da6c28aaSamw 35da6c28aaSamw #include <sys/errno.h> 36da6c28aaSamw #include <stdio.h> 37da6c28aaSamw #include <time.h> 38da6c28aaSamw #include <strings.h> 39da6c28aaSamw 40da6c28aaSamw #include <smbsrv/libsmb.h> 418d7e4166Sjose borrego #include <smbsrv/libmlsvc.h> 42da6c28aaSamw #include <smbsrv/smbinfo.h> 43da6c28aaSamw #include <smbsrv/ndl/srvsvc.ndl> 44da6c28aaSamw 45da6c28aaSamw /* 46da6c28aaSamw * Information level for NetShareGetInfo. 47da6c28aaSamw */ 48da6c28aaSamw DWORD srvsvc_info_level = 1; 49da6c28aaSamw 50da6c28aaSamw /* 518d7e4166Sjose borrego * Bind to the the SRVSVC. 52da6c28aaSamw * 5355bf511dSas * If username argument is NULL, an anonymous connection will be established. 5455bf511dSas * Otherwise, an authenticated connection will be established. 55da6c28aaSamw */ 5655bf511dSas static int 578d7e4166Sjose borrego srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle) 58da6c28aaSamw { 59a0aa776eSAlan Wright smb_domainex_t di; 60da6c28aaSamw 61da6c28aaSamw if (server == NULL || domain == NULL) { 628d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 6355bf511dSas return (-1); 64da6c28aaSamw 658d7e4166Sjose borrego server = di.d_dc; 66a0aa776eSAlan Wright domain = di.d_primary.di_nbname; 6755bf511dSas } 68da6c28aaSamw 6955bf511dSas if (username == NULL) 7055bf511dSas username = MLSVC_ANON_USER; 71da6c28aaSamw 728d7e4166Sjose borrego if (ndr_rpc_bind(handle, server, domain, username, "SRVSVC") < 0) 73da6c28aaSamw return (-1); 74da6c28aaSamw 758d7e4166Sjose borrego return (0); 76da6c28aaSamw } 77da6c28aaSamw 78da6c28aaSamw /* 798d7e4166Sjose borrego * Unbind the SRVSVC connection. 80da6c28aaSamw */ 818d7e4166Sjose borrego static void 828d7e4166Sjose borrego srvsvc_close(mlsvc_handle_t *handle) 83da6c28aaSamw { 848d7e4166Sjose borrego ndr_rpc_unbind(handle); 85da6c28aaSamw } 86da6c28aaSamw 87da6c28aaSamw /* 88da6c28aaSamw * This is a client side routine for NetShareGetInfo. 89da6c28aaSamw * Levels 0 and 1 work with an anonymous connection but 90da6c28aaSamw * level 2 requires administrator access. 91da6c28aaSamw */ 92da6c28aaSamw int 93da6c28aaSamw srvsvc_net_share_get_info(char *server, char *domain, char *netname) 94da6c28aaSamw { 95da6c28aaSamw struct mlsm_NetShareGetInfo arg; 96da6c28aaSamw mlsvc_handle_t handle; 97da6c28aaSamw int rc; 98da6c28aaSamw int opnum; 99eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_0 *info0; 100eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_1 *info1; 101eb1d736bSafshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetShareInfo_2 *info2; 102da6c28aaSamw int len; 103a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 104da6c28aaSamw 105da6c28aaSamw if (netname == NULL) 106da6c28aaSamw return (-1); 107da6c28aaSamw 108da6c28aaSamw if (srvsvc_info_level == 2) 109a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 110da6c28aaSamw 1118d7e4166Sjose borrego if (srvsvc_open(server, domain, user, &handle) != 0) 112da6c28aaSamw return (-1); 113da6c28aaSamw 114da6c28aaSamw opnum = SRVSVC_OPNUM_NetShareGetInfo; 115da6c28aaSamw bzero(&arg, sizeof (struct mlsm_NetShareGetInfo)); 116da6c28aaSamw 117da6c28aaSamw len = strlen(server) + 4; 1188d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 119da6c28aaSamw if (arg.servername == NULL) { 1208d7e4166Sjose borrego srvsvc_close(&handle); 121da6c28aaSamw return (-1); 122da6c28aaSamw } 123da6c28aaSamw 124da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 125da6c28aaSamw arg.netname = (LPTSTR)netname; 126da6c28aaSamw arg.level = srvsvc_info_level; /* share information level */ 127da6c28aaSamw 1288d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 129da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 1308d7e4166Sjose borrego srvsvc_close(&handle); 131da6c28aaSamw return (-1); 132da6c28aaSamw } 133da6c28aaSamw 134da6c28aaSamw switch (arg.result.switch_value) { 135da6c28aaSamw case 0: 136da6c28aaSamw info0 = arg.result.ru.info0; 137da6c28aaSamw smb_tracef("srvsvc shi0_netname=%s", info0->shi0_netname); 138da6c28aaSamw break; 139da6c28aaSamw 140da6c28aaSamw case 1: 141da6c28aaSamw info1 = arg.result.ru.info1; 142da6c28aaSamw smb_tracef("srvsvc shi1_netname=%s", info1->shi1_netname); 143da6c28aaSamw smb_tracef("srvsvc shi1_type=%u", info1->shi1_type); 144da6c28aaSamw 145da6c28aaSamw if (info1->shi1_comment) 146da6c28aaSamw smb_tracef("srvsvc shi1_comment=%s", 147da6c28aaSamw info1->shi1_comment); 148da6c28aaSamw break; 149da6c28aaSamw 150da6c28aaSamw case 2: 151da6c28aaSamw info2 = arg.result.ru.info2; 152da6c28aaSamw smb_tracef("srvsvc shi2_netname=%s", info2->shi2_netname); 153da6c28aaSamw smb_tracef("srvsvc shi2_type=%u", info2->shi2_type); 154da6c28aaSamw 155da6c28aaSamw if (info2->shi2_comment) 156da6c28aaSamw smb_tracef("srvsvc shi2_comment=%s", 157da6c28aaSamw info2->shi2_comment); 158da6c28aaSamw 159da6c28aaSamw smb_tracef("srvsvc shi2_perms=%d", info2->shi2_permissions); 160da6c28aaSamw smb_tracef("srvsvc shi2_max_use=%d", info2->shi2_max_uses); 161da6c28aaSamw smb_tracef("srvsvc shi2_cur_use=%d", info2->shi2_current_uses); 162da6c28aaSamw 163da6c28aaSamw if (info2->shi2_path) 164da6c28aaSamw smb_tracef("srvsvc shi2_path=%s", info2->shi2_path); 165da6c28aaSamw 166da6c28aaSamw if (info2->shi2_passwd) 167da6c28aaSamw smb_tracef("srvsvc shi2_passwd=%s", info2->shi2_passwd); 168da6c28aaSamw break; 169da6c28aaSamw 170da6c28aaSamw default: 171da6c28aaSamw smb_tracef("srvsvc: unknown level"); 172da6c28aaSamw break; 173da6c28aaSamw } 174da6c28aaSamw 1758d7e4166Sjose borrego srvsvc_close(&handle); 176da6c28aaSamw return (0); 177da6c28aaSamw } 178da6c28aaSamw 179da6c28aaSamw /* 180da6c28aaSamw * This is a client side routine for NetSessionEnum. 181da6c28aaSamw * NetSessionEnum requires administrator rights. 182da6c28aaSamw */ 183da6c28aaSamw int 184da6c28aaSamw srvsvc_net_session_enum(char *server, char *domain, char *netname) 185da6c28aaSamw { 186da6c28aaSamw struct mslm_NetSessionEnum arg; 187da6c28aaSamw mlsvc_handle_t handle; 188da6c28aaSamw int rc; 189da6c28aaSamw int opnum; 190da6c28aaSamw struct mslm_infonres infonres; 191da6c28aaSamw struct mslm_SESSION_INFO_1 *nsi1; 192da6c28aaSamw int len; 193a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 194da6c28aaSamw 195da6c28aaSamw if (netname == NULL) 196da6c28aaSamw return (-1); 197da6c28aaSamw 198a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 199a0aa776eSAlan Wright 2008d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle); 201da6c28aaSamw if (rc != 0) 202da6c28aaSamw return (-1); 203da6c28aaSamw 204da6c28aaSamw opnum = SRVSVC_OPNUM_NetSessionEnum; 205da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetSessionEnum)); 206da6c28aaSamw 207da6c28aaSamw len = strlen(server) + 4; 2088d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 209da6c28aaSamw if (arg.servername == NULL) { 2108d7e4166Sjose borrego srvsvc_close(&handle); 211da6c28aaSamw return (-1); 212da6c28aaSamw } 213da6c28aaSamw 214da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 215da6c28aaSamw infonres.entriesread = 0; 216da6c28aaSamw infonres.entries = 0; 217da6c28aaSamw arg.level = 1; 218da6c28aaSamw arg.result.level = 1; 219da6c28aaSamw arg.result.bufptr.p = &infonres; 220da6c28aaSamw arg.resume_handle = 0; 221da6c28aaSamw arg.pref_max_len = 0xFFFFFFFF; 222da6c28aaSamw 2238d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 224da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 2258d7e4166Sjose borrego srvsvc_close(&handle); 226da6c28aaSamw return (-1); 227da6c28aaSamw } 228da6c28aaSamw 229da6c28aaSamw /* Only the first session info is dereferenced. */ 230da6c28aaSamw nsi1 = ((struct mslm_infonres *)arg.result.bufptr.p)->entries; 231da6c28aaSamw 232da6c28aaSamw smb_tracef("srvsvc switch_value=%d", arg.level); 233da6c28aaSamw smb_tracef("srvsvc sesi1_cname=%s", nsi1->sesi1_cname); 234da6c28aaSamw smb_tracef("srvsvc sesi1_uname=%s", nsi1->sesi1_uname); 235da6c28aaSamw smb_tracef("srvsvc sesi1_nopens=%u", nsi1->sesi1_nopens); 236da6c28aaSamw smb_tracef("srvsvc sesi1_time=%u", nsi1->sesi1_time); 237da6c28aaSamw smb_tracef("srvsvc sesi1_itime=%u", nsi1->sesi1_itime); 238da6c28aaSamw smb_tracef("srvsvc sesi1_uflags=%u", nsi1->sesi1_uflags); 239da6c28aaSamw 2408d7e4166Sjose borrego srvsvc_close(&handle); 241da6c28aaSamw return (0); 242da6c28aaSamw } 243da6c28aaSamw 244da6c28aaSamw /* 245da6c28aaSamw * This is a client side routine for NetConnectEnum. 246da6c28aaSamw * NetConnectEnum requires administrator rights. 247da6c28aaSamw * Level 0 and level 1 requests are supported. 248da6c28aaSamw */ 249da6c28aaSamw int 250da6c28aaSamw srvsvc_net_connect_enum(char *server, char *domain, char *netname, int level) 251da6c28aaSamw { 252da6c28aaSamw struct mslm_NetConnectEnum arg; 253da6c28aaSamw mlsvc_handle_t handle; 254da6c28aaSamw int rc; 255da6c28aaSamw int opnum; 256da6c28aaSamw struct mslm_NetConnectInfo1 info1; 257da6c28aaSamw struct mslm_NetConnectInfo0 info0; 258da6c28aaSamw struct mslm_NetConnectInfoBuf1 *cib1; 259da6c28aaSamw int len; 260a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 261da6c28aaSamw 262da6c28aaSamw if (netname == NULL) 263da6c28aaSamw return (-1); 264da6c28aaSamw 265a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 266a0aa776eSAlan Wright 2678d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle); 268da6c28aaSamw if (rc != 0) 269da6c28aaSamw return (-1); 270da6c28aaSamw 271da6c28aaSamw opnum = SRVSVC_OPNUM_NetConnectEnum; 272da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetConnectEnum)); 273da6c28aaSamw 274da6c28aaSamw len = strlen(server) + 4; 2758d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 276da6c28aaSamw if (arg.servername == NULL) { 2778d7e4166Sjose borrego srvsvc_close(&handle); 278da6c28aaSamw return (-1); 279da6c28aaSamw } 280da6c28aaSamw 281da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 282da6c28aaSamw arg.qualifier = (LPTSTR)netname; 283da6c28aaSamw 284da6c28aaSamw switch (level) { 285da6c28aaSamw case 0: 286da6c28aaSamw arg.info.level = 0; 287da6c28aaSamw arg.info.switch_value = 0; 288da6c28aaSamw arg.info.ru.info0 = &info0; 289da6c28aaSamw info0.entries_read = 0; 290da6c28aaSamw info0.ci0 = 0; 291da6c28aaSamw break; 292da6c28aaSamw case 1: 293da6c28aaSamw arg.info.level = 1; 294da6c28aaSamw arg.info.switch_value = 1; 295da6c28aaSamw arg.info.ru.info1 = &info1; 296da6c28aaSamw info1.entries_read = 0; 297da6c28aaSamw info1.ci1 = 0; 298da6c28aaSamw break; 299da6c28aaSamw default: 3008d7e4166Sjose borrego srvsvc_close(&handle); 301da6c28aaSamw return (-1); 302da6c28aaSamw } 303da6c28aaSamw 304da6c28aaSamw arg.resume_handle = 0; 305da6c28aaSamw arg.pref_max_len = 0xFFFFFFFF; 306da6c28aaSamw 3078d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 308da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 3098d7e4166Sjose borrego srvsvc_close(&handle); 310da6c28aaSamw return (-1); 311da6c28aaSamw } 312da6c28aaSamw 313da6c28aaSamw smb_tracef("srvsvc switch_value=%d", arg.info.switch_value); 314da6c28aaSamw 315da6c28aaSamw switch (level) { 316da6c28aaSamw case 0: 317da6c28aaSamw if (arg.info.ru.info0 && arg.info.ru.info0->ci0) { 318da6c28aaSamw smb_tracef("srvsvc coni0_id=%x", 319da6c28aaSamw arg.info.ru.info0->ci0->coni0_id); 320da6c28aaSamw } 321da6c28aaSamw break; 322da6c28aaSamw case 1: 323da6c28aaSamw if (arg.info.ru.info1 && arg.info.ru.info1->ci1) { 324da6c28aaSamw cib1 = arg.info.ru.info1->ci1; 325da6c28aaSamw 326da6c28aaSamw smb_tracef("srvsvc coni_uname=%s", 327da6c28aaSamw cib1->coni1_username ? 328da6c28aaSamw (char *)cib1->coni1_username : "(null)"); 329da6c28aaSamw smb_tracef("srvsvc coni1_netname=%s", 330da6c28aaSamw cib1->coni1_netname ? 331da6c28aaSamw (char *)cib1->coni1_netname : "(null)"); 332da6c28aaSamw smb_tracef("srvsvc coni1_nopens=%u", 333da6c28aaSamw cib1->coni1_num_opens); 334da6c28aaSamw smb_tracef("srvsvc coni1_time=%u", cib1->coni1_time); 335da6c28aaSamw smb_tracef("srvsvc coni1_num_users=%u", 336da6c28aaSamw cib1->coni1_num_users); 337da6c28aaSamw } 338da6c28aaSamw break; 339da6c28aaSamw 340da6c28aaSamw default: 341da6c28aaSamw smb_tracef("srvsvc: unknown level"); 342da6c28aaSamw break; 343da6c28aaSamw } 344da6c28aaSamw 3458d7e4166Sjose borrego srvsvc_close(&handle); 346da6c28aaSamw return (0); 347da6c28aaSamw } 348da6c28aaSamw 349a0aa776eSAlan Wright /* 350a0aa776eSAlan Wright * Windows 95+ and Windows NT4.0 both report the version as 4.0. 351a0aa776eSAlan Wright * Windows 2000+ reports the version as 5.x. 352a0aa776eSAlan Wright */ 3531fcced4cSJordan Brown int 3541fcced4cSJordan Brown srvsvc_net_server_getinfo(char *server, char *domain, 3551fcced4cSJordan Brown srvsvc_server_info_t *svinfo) 3561fcced4cSJordan Brown { 3571fcced4cSJordan Brown mlsvc_handle_t handle; 3581fcced4cSJordan Brown struct mslm_NetServerGetInfo arg; 3591fcced4cSJordan Brown struct mslm_SERVER_INFO_101 *sv101; 3601fcced4cSJordan Brown int len, opnum, rc; 361a0aa776eSAlan Wright char user[SMB_USERNAME_MAXLEN]; 362a0aa776eSAlan Wright 363a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 3641fcced4cSJordan Brown 3651fcced4cSJordan Brown if (srvsvc_open(server, domain, user, &handle) != 0) 3661fcced4cSJordan Brown return (-1); 3671fcced4cSJordan Brown 3681fcced4cSJordan Brown opnum = SRVSVC_OPNUM_NetServerGetInfo; 3691fcced4cSJordan Brown bzero(&arg, sizeof (arg)); 3701fcced4cSJordan Brown 3711fcced4cSJordan Brown len = strlen(server) + 4; 3721fcced4cSJordan Brown arg.servername = ndr_rpc_malloc(&handle, len); 3731fcced4cSJordan Brown if (arg.servername == NULL) 3741fcced4cSJordan Brown return (-1); 3751fcced4cSJordan Brown 3761fcced4cSJordan Brown (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 3771fcced4cSJordan Brown arg.level = 101; 3781fcced4cSJordan Brown 3791fcced4cSJordan Brown rc = ndr_rpc_call(&handle, opnum, &arg); 3801fcced4cSJordan Brown if ((rc != 0) || (arg.status != 0)) { 3811fcced4cSJordan Brown srvsvc_close(&handle); 3821fcced4cSJordan Brown return (-1); 3831fcced4cSJordan Brown } 3841fcced4cSJordan Brown 3851fcced4cSJordan Brown sv101 = arg.result.bufptr.bufptr101; 3861fcced4cSJordan Brown 3871fcced4cSJordan Brown bzero(svinfo, sizeof (srvsvc_server_info_t)); 3881fcced4cSJordan Brown svinfo->sv_platform_id = sv101->sv101_platform_id; 3891fcced4cSJordan Brown svinfo->sv_version_major = sv101->sv101_version_major; 3901fcced4cSJordan Brown svinfo->sv_version_minor = sv101->sv101_version_minor; 3911fcced4cSJordan Brown svinfo->sv_type = sv101->sv101_type; 3921fcced4cSJordan Brown if (sv101->sv101_name) 3931fcced4cSJordan Brown svinfo->sv_name = strdup((char *)sv101->sv101_name); 3941fcced4cSJordan Brown if (sv101->sv101_comment) 3951fcced4cSJordan Brown svinfo->sv_comment = strdup((char *)sv101->sv101_comment); 3961fcced4cSJordan Brown 397a0aa776eSAlan Wright if (svinfo->sv_type & SV_TYPE_WFW) 398a0aa776eSAlan Wright svinfo->sv_os = NATIVE_OS_WIN95; 399a0aa776eSAlan Wright if (svinfo->sv_type & SV_TYPE_WINDOWS) 400a0aa776eSAlan Wright svinfo->sv_os = NATIVE_OS_WIN95; 401a0aa776eSAlan Wright if ((svinfo->sv_type & SV_TYPE_NT) || 402a0aa776eSAlan Wright (svinfo->sv_type & SV_TYPE_SERVER_NT)) 403a0aa776eSAlan Wright svinfo->sv_os = NATIVE_OS_WINNT; 404a0aa776eSAlan Wright if (svinfo->sv_version_major > 4) 405a0aa776eSAlan Wright svinfo->sv_os = NATIVE_OS_WIN2000; 406a0aa776eSAlan Wright 4071fcced4cSJordan Brown srvsvc_close(&handle); 4081fcced4cSJordan Brown return (0); 4091fcced4cSJordan Brown } 4101fcced4cSJordan Brown 411da6c28aaSamw /* 412da6c28aaSamw * Synchronize the local system clock with the domain controller. 413da6c28aaSamw */ 414da6c28aaSamw void 415da6c28aaSamw srvsvc_timesync(void) 416da6c28aaSamw { 417a0aa776eSAlan Wright smb_domainex_t di; 418da6c28aaSamw struct timeval tv; 419da6c28aaSamw struct tm tm; 420da6c28aaSamw time_t tsecs; 421da6c28aaSamw 4228d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 423da6c28aaSamw return; 424da6c28aaSamw 425a0aa776eSAlan Wright if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) 426a0aa776eSAlan Wright != 0) 427da6c28aaSamw return; 428da6c28aaSamw 429da6c28aaSamw if (settimeofday(&tv, 0)) 430da6c28aaSamw smb_tracef("unable to set system time"); 431da6c28aaSamw 432da6c28aaSamw tsecs = time(0); 433da6c28aaSamw (void) localtime_r(&tsecs, &tm); 434da6c28aaSamw smb_tracef("SrvsvcTimeSync %s", ctime((time_t *)&tv.tv_sec)); 435da6c28aaSamw } 436da6c28aaSamw 437da6c28aaSamw /* 438da6c28aaSamw * NetRemoteTOD to get the current GMT time from a Windows NT server. 439da6c28aaSamw */ 440da6c28aaSamw int 441da6c28aaSamw srvsvc_gettime(unsigned long *t) 442da6c28aaSamw { 443a0aa776eSAlan Wright smb_domainex_t di; 444da6c28aaSamw struct timeval tv; 445da6c28aaSamw struct tm tm; 446da6c28aaSamw 4478d7e4166Sjose borrego if (!smb_domain_getinfo(&di)) 448da6c28aaSamw return (-1); 449da6c28aaSamw 450a0aa776eSAlan Wright if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) 451a0aa776eSAlan Wright != 0) 452da6c28aaSamw return (-1); 453da6c28aaSamw 454da6c28aaSamw *t = tv.tv_sec; 455da6c28aaSamw return (0); 456da6c28aaSamw } 457da6c28aaSamw 458da6c28aaSamw /* 459da6c28aaSamw * This is a client side routine for NetRemoteTOD, which gets the time 460da6c28aaSamw * and date from a remote system. The time information is returned in 461da6c28aaSamw * the timeval and tm. 462da6c28aaSamw * 463da6c28aaSamw * typedef struct _TIME_OF_DAY_INFO { 464da6c28aaSamw * DWORD tod_elapsedt; // seconds since 00:00:00 January 1 1970 GMT 465da6c28aaSamw * DWORD tod_msecs; // arbitrary milliseconds (since reset) 466da6c28aaSamw * DWORD tod_hours; // current hour [0-23] 467da6c28aaSamw * DWORD tod_mins; // current minute [0-59] 468da6c28aaSamw * DWORD tod_secs; // current second [0-59] 469da6c28aaSamw * DWORD tod_hunds; // current hundredth (0.01) second [0-99] 470da6c28aaSamw * LONG tod_timezone; // time zone of the server 471da6c28aaSamw * DWORD tod_tinterval; // clock tick time interval 472da6c28aaSamw * DWORD tod_day; // day of the month [1-31] 473da6c28aaSamw * DWORD tod_month; // month of the year [1-12] 474da6c28aaSamw * DWORD tod_year; // current year 475da6c28aaSamw * DWORD tod_weekday; // day of the week since sunday [0-6] 476da6c28aaSamw * } TIME_OF_DAY_INFO; 477da6c28aaSamw * 478da6c28aaSamw * The time zone of the server is calculated in minutes from Greenwich 479da6c28aaSamw * Mean Time (GMT). For time zones west of Greenwich, the value is 480da6c28aaSamw * positive; for time zones east of Greenwich, the value is negative. 481da6c28aaSamw * A value of -1 indicates that the time zone is undefined. 482da6c28aaSamw * 483da6c28aaSamw * The clock tick value represents a resolution of one ten-thousandth 484da6c28aaSamw * (0.0001) second. 485da6c28aaSamw */ 486da6c28aaSamw int 487da6c28aaSamw srvsvc_net_remote_tod(char *server, char *domain, struct timeval *tv, 488da6c28aaSamw struct tm *tm) 489da6c28aaSamw { 4909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_NetRemoteTOD arg; 4919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States struct mslm_TIME_OF_DAY_INFO *tod; 4929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States mlsvc_handle_t handle; 4939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int rc; 4949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int opnum; 4959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int len; 4969fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States char user[SMB_USERNAME_MAXLEN]; 497a0aa776eSAlan Wright 498a0aa776eSAlan Wright smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); 499da6c28aaSamw 5008d7e4166Sjose borrego rc = srvsvc_open(server, domain, user, &handle); 501da6c28aaSamw if (rc != 0) 502da6c28aaSamw return (-1); 503da6c28aaSamw 504da6c28aaSamw opnum = SRVSVC_OPNUM_NetRemoteTOD; 505da6c28aaSamw bzero(&arg, sizeof (struct mslm_NetRemoteTOD)); 506da6c28aaSamw 507da6c28aaSamw len = strlen(server) + 4; 5088d7e4166Sjose borrego arg.servername = ndr_rpc_malloc(&handle, len); 509da6c28aaSamw if (arg.servername == NULL) { 5108d7e4166Sjose borrego srvsvc_close(&handle); 511da6c28aaSamw return (-1); 512da6c28aaSamw } 513da6c28aaSamw 514da6c28aaSamw (void) snprintf((char *)arg.servername, len, "\\\\%s", server); 515da6c28aaSamw 5168d7e4166Sjose borrego rc = ndr_rpc_call(&handle, opnum, &arg); 517da6c28aaSamw if ((rc != 0) || (arg.status != 0)) { 5188d7e4166Sjose borrego srvsvc_close(&handle); 519da6c28aaSamw return (-1); 520da6c28aaSamw } 521da6c28aaSamw 522da6c28aaSamw /* 523da6c28aaSamw * We're assigning milliseconds to microseconds 524da6c28aaSamw * here but the value's not really relevant. 525da6c28aaSamw */ 526da6c28aaSamw tod = arg.bufptr; 527da6c28aaSamw 528da6c28aaSamw if (tv) { 529da6c28aaSamw tv->tv_sec = tod->tod_elapsedt; 530da6c28aaSamw tv->tv_usec = tod->tod_msecs; 531da6c28aaSamw } 532da6c28aaSamw 533da6c28aaSamw if (tm) { 534da6c28aaSamw tm->tm_sec = tod->tod_secs; 535da6c28aaSamw tm->tm_min = tod->tod_mins; 536da6c28aaSamw tm->tm_hour = tod->tod_hours; 537da6c28aaSamw tm->tm_mday = tod->tod_day; 538da6c28aaSamw tm->tm_mon = tod->tod_month - 1; 539da6c28aaSamw tm->tm_year = tod->tod_year - 1900; 540da6c28aaSamw tm->tm_wday = tod->tod_weekday; 541da6c28aaSamw } 542da6c28aaSamw 5438d7e4166Sjose borrego srvsvc_close(&handle); 544da6c28aaSamw return (0); 545da6c28aaSamw } 546da6c28aaSamw 547da6c28aaSamw void 548da6c28aaSamw srvsvc_net_test(char *server, char *domain, char *netname) 549da6c28aaSamw { 550a0aa776eSAlan Wright smb_domainex_t di; 5511fcced4cSJordan Brown srvsvc_server_info_t svinfo; 552da6c28aaSamw 553da6c28aaSamw (void) smb_tracef("%s %s %s", server, domain, netname); 554da6c28aaSamw 5558d7e4166Sjose borrego if (smb_domain_getinfo(&di)) { 5568d7e4166Sjose borrego server = di.d_dc; 557a0aa776eSAlan Wright domain = di.d_primary.di_nbname; 558da6c28aaSamw } 559da6c28aaSamw 5601fcced4cSJordan Brown if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) { 5611fcced4cSJordan Brown smb_tracef("NetServerGetInfo: %s %s (%d.%d) id=%d type=0x%08x", 5621fcced4cSJordan Brown svinfo.sv_name ? svinfo.sv_name : "NULL", 5631fcced4cSJordan Brown svinfo.sv_comment ? svinfo.sv_comment : "NULL", 5641fcced4cSJordan Brown svinfo.sv_version_major, svinfo.sv_version_minor, 5651fcced4cSJordan Brown svinfo.sv_platform_id, svinfo.sv_type); 5661fcced4cSJordan Brown 5671fcced4cSJordan Brown free(svinfo.sv_name); 5681fcced4cSJordan Brown free(svinfo.sv_comment); 5691fcced4cSJordan Brown } 5701fcced4cSJordan Brown 571da6c28aaSamw (void) srvsvc_net_share_get_info(server, domain, netname); 572da6c28aaSamw #if 0 573da6c28aaSamw /* 574da6c28aaSamw * The NetSessionEnum server-side definition was updated. 575da6c28aaSamw * Disabled until the client-side has been updated. 576da6c28aaSamw */ 577da6c28aaSamw (void) srvsvc_net_session_enum(server, domain, netname); 578da6c28aaSamw #endif 579da6c28aaSamw (void) srvsvc_net_connect_enum(server, domain, netname, 0); 580da6c28aaSamw (void) srvsvc_net_connect_enum(server, domain, netname, 1); 581da6c28aaSamw } 582