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 */ 21da6c28aaSamw /* 227f667e74Sjose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * This module handles the primary domain controller location protocol. 28da6c28aaSamw * The document claims to be version 1.15 of the browsing protocol. It also 29da6c28aaSamw * claims to specify the mailslot protocol. 30da6c28aaSamw * 31da6c28aaSamw * The NETLOGON protocol uses \MAILSLOT\NET mailslots. The protocol 32da6c28aaSamw * specification is incomplete, contains errors and is out-of-date but 33da6c28aaSamw * it does provide some useful background information. The document 34da6c28aaSamw * doesn't mention the NETLOGON_SAMLOGON version of the protocol. 35da6c28aaSamw */ 36da6c28aaSamw 37da6c28aaSamw #include <stdlib.h> 38da6c28aaSamw #include <syslog.h> 39da6c28aaSamw #include <alloca.h> 40da6c28aaSamw #include <arpa/inet.h> 41da6c28aaSamw #include <resolv.h> 42da6c28aaSamw 43da6c28aaSamw #include <smbsrv/mailslot.h> 44da6c28aaSamw #include <smbsrv/libsmbns.h> 45da6c28aaSamw #include <smbns_browser.h> 46da6c28aaSamw #include <smbns_netbios.h> 47da6c28aaSamw 48da6c28aaSamw static void smb_netlogon_query(struct name_entry *server, char *mailbox, 49da6c28aaSamw char *domain); 50da6c28aaSamw 5129bd2886SAlan Wright static void smb_netlogon_samlogon(struct name_entry *, char *, 5229bd2886SAlan Wright char *, smb_sid_t *); 53da6c28aaSamw 54da6c28aaSamw static void smb_netlogon_send(struct name_entry *name, char *domain, 55da6c28aaSamw unsigned char *buffer, int count); 56da6c28aaSamw 57da6c28aaSamw static void smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr); 583db3f65cSamw static int smb_better_dc(uint32_t cur_ip, uint32_t new_ip); 59da6c28aaSamw 608d7e4166Sjose borrego /* 618d7e4166Sjose borrego * ntdomain_info 628d7e4166Sjose borrego * Temporary. It should be removed once NBTD is integrated. 638d7e4166Sjose borrego */ 648d7e4166Sjose borrego extern smb_ntdomain_t ntdomain_info; 658d7e4166Sjose borrego extern mutex_t ntdomain_mtx; 668d7e4166Sjose borrego extern cond_t ntdomain_cv; 67da6c28aaSamw 68da6c28aaSamw /* 69da6c28aaSamw * smb_netlogon_request 70da6c28aaSamw * 71da6c28aaSamw * This is the entry point locating the resource domain PDC. A netlogon 72da6c28aaSamw * request is sent using the specified protocol on the specified network. 73da6c28aaSamw * Note that we need to know the domain SID in order to use the samlogon 74da6c28aaSamw * format. 75da6c28aaSamw * 76da6c28aaSamw * Netlogon responses are received asynchronously and eventually handled 77da6c28aaSamw * in smb_netlogon_receive. 78da6c28aaSamw */ 79da6c28aaSamw void 8029bd2886SAlan Wright smb_netlogon_request(struct name_entry *server, char *domain) 81da6c28aaSamw { 82a0aa776eSAlan Wright smb_domain_t di; 8329bd2886SAlan Wright smb_sid_t *sid = NULL; 8429bd2886SAlan Wright int protocol = NETLOGON_PROTO_NETLOGON; 85da6c28aaSamw 867b59d02dSjb150015 if (domain == NULL || *domain == '\0') 87da6c28aaSamw return; 88da6c28aaSamw 898d7e4166Sjose borrego (void) mutex_lock(&ntdomain_mtx); 908d7e4166Sjose borrego (void) strlcpy(ntdomain_info.n_domain, domain, 918d7e4166Sjose borrego sizeof (ntdomain_info.n_domain)); 928d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 93da6c28aaSamw 9429bd2886SAlan Wright smb_config_getdomaininfo(di.di_nbname, NULL, di.di_sid, NULL, NULL); 95*bbf6f00cSJordan Brown if (smb_strcasecmp(di.di_nbname, domain, 0) == 0) { 9629bd2886SAlan Wright if ((sid = smb_sid_fromstr(di.di_sid)) != NULL) 9729bd2886SAlan Wright protocol = NETLOGON_PROTO_SAMLOGON; 9829bd2886SAlan Wright } 9929bd2886SAlan Wright 10029bd2886SAlan Wright if (protocol == NETLOGON_PROTO_SAMLOGON) 10129bd2886SAlan Wright smb_netlogon_samlogon(server, MAILSLOT_NETLOGON_SAMLOGON_RDC, 10229bd2886SAlan Wright domain, sid); 103da6c28aaSamw else 10429bd2886SAlan Wright smb_netlogon_query(server, MAILSLOT_NETLOGON_RDC, domain); 10529bd2886SAlan Wright 10629bd2886SAlan Wright smb_sid_free(sid); 107da6c28aaSamw } 108da6c28aaSamw 109da6c28aaSamw /* 110da6c28aaSamw * smb_netlogon_receive 111da6c28aaSamw * 112da6c28aaSamw * This is where we handle all incoming NetLogon messages. Currently, we 113da6c28aaSamw * ignore requests from anyone else. We are only interested in responses 114da6c28aaSamw * to our own requests. The NetLogonResponse provides the name of the PDC. 115da6c28aaSamw * If we don't already have a controller name, we use the name provided 116da6c28aaSamw * in the message. Otherwise we use the name already in the environment. 117da6c28aaSamw */ 118da6c28aaSamw void 119da6c28aaSamw smb_netlogon_receive(struct datagram *datagram, 120da6c28aaSamw char *mailbox, 121da6c28aaSamw unsigned char *data, 122da6c28aaSamw int datalen) 123da6c28aaSamw { 124da6c28aaSamw struct netlogon_opt { 125da6c28aaSamw char *mailslot; 126da6c28aaSamw void (*handler)(); 127da6c28aaSamw } netlogon_opt[] = { 128da6c28aaSamw { MAILSLOT_NETLOGON_RDC, smb_netlogon_rdc_rsp }, 129da6c28aaSamw { MAILSLOT_NETLOGON_SAMLOGON_RDC, smb_netlogon_rdc_rsp }, 130da6c28aaSamw }; 131da6c28aaSamw 132da6c28aaSamw smb_msgbuf_t mb; 133da6c28aaSamw unsigned short opcode; 134da6c28aaSamw char src_name[SMB_PI_MAX_HOST]; 135*bbf6f00cSJordan Brown smb_wchar_t unicode_src_name[SMB_PI_MAX_HOST]; 136da6c28aaSamw uint32_t src_ipaddr; 137da6c28aaSamw char *junk; 138da6c28aaSamw char *primary; 139da6c28aaSamw char *domain; 140da6c28aaSamw int i; 141da6c28aaSamw char ipstr[16]; 142da6c28aaSamw int rc; 143da6c28aaSamw 144da6c28aaSamw src_ipaddr = datagram->src.addr_list.sin.sin_addr.s_addr; 145da6c28aaSamw 146da6c28aaSamw /* 147da6c28aaSamw * The datagram->src.name is in oem codepage format. 148da6c28aaSamw * Therefore, we need to convert it to unicode and 149da6c28aaSamw * store it in multi-bytes format. 150da6c28aaSamw */ 151*bbf6f00cSJordan Brown (void) oemtoucs(unicode_src_name, (char *)datagram->src.name, 152*bbf6f00cSJordan Brown SMB_PI_MAX_HOST, OEM_CPG_850); 153*bbf6f00cSJordan Brown (void) smb_wcstombs(src_name, unicode_src_name, SMB_PI_MAX_HOST); 154da6c28aaSamw 155da6c28aaSamw (void) trim_whitespace(src_name); 156da6c28aaSamw 157da6c28aaSamw (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr), ipstr, 158da6c28aaSamw sizeof (ipstr)); 159da6c28aaSamw syslog(LOG_DEBUG, "NetLogonReceive: src=%s [%s], mbx=%s", 160da6c28aaSamw src_name, ipstr, mailbox); 161da6c28aaSamw 162da6c28aaSamw smb_msgbuf_init(&mb, data, datalen, 0); 163da6c28aaSamw 164da6c28aaSamw if (smb_msgbuf_decode(&mb, "w", &opcode) < 0) { 165da6c28aaSamw syslog(LOG_ERR, "NetLogonReceive: decode error"); 166da6c28aaSamw smb_msgbuf_term(&mb); 167da6c28aaSamw return; 168da6c28aaSamw } 169da6c28aaSamw 170da6c28aaSamw switch (opcode) { 171da6c28aaSamw case LOGON_PRIMARY_RESPONSE: 172da6c28aaSamw /* 173da6c28aaSamw * Message contains: 174da6c28aaSamw * PDC name (MBS), PDC name (Unicode), Domain name (unicode) 175da6c28aaSamw */ 176da6c28aaSamw rc = smb_msgbuf_decode(&mb, "sUU", &junk, &primary, &domain); 177da6c28aaSamw if (rc < 0) { 178da6c28aaSamw syslog(LOG_ERR, 179da6c28aaSamw "NetLogonResponse: opcode %d decode error", 180da6c28aaSamw opcode); 181da6c28aaSamw smb_msgbuf_term(&mb); 182da6c28aaSamw return; 183da6c28aaSamw } 184da6c28aaSamw break; 185da6c28aaSamw 186da6c28aaSamw case LOGON_SAM_LOGON_RESPONSE: 187da6c28aaSamw case LOGON_SAM_USER_UNKNOWN: 188da6c28aaSamw /* 189da6c28aaSamw * Message contains: 190da6c28aaSamw * PDC name, User name, Domain name (all unicode) 191da6c28aaSamw */ 192da6c28aaSamw rc = smb_msgbuf_decode(&mb, "UUU", &primary, &junk, &domain); 193da6c28aaSamw if (rc < 0) { 194da6c28aaSamw syslog(LOG_ERR, 195da6c28aaSamw "NetLogonResponse: opcode %d decode error", 196da6c28aaSamw opcode); 197da6c28aaSamw smb_msgbuf_term(&mb); 198da6c28aaSamw return; 199da6c28aaSamw } 200da6c28aaSamw 201da6c28aaSamw /* 202da6c28aaSamw * skip past the "\\" prefix 203da6c28aaSamw */ 204da6c28aaSamw primary += strspn(primary, "\\"); 205da6c28aaSamw break; 206da6c28aaSamw 207da6c28aaSamw default: 208da6c28aaSamw /* 209da6c28aaSamw * We don't respond to PDC discovery requests. 210da6c28aaSamw */ 211da6c28aaSamw syslog(LOG_DEBUG, "NetLogonReceive: opcode 0x%04x", opcode); 212da6c28aaSamw smb_msgbuf_term(&mb); 213da6c28aaSamw return; 214da6c28aaSamw } 215da6c28aaSamw 216a0aa776eSAlan Wright if (domain == NULL || primary == NULL) { 217da6c28aaSamw syslog(LOG_ERR, "NetLogonResponse: malformed packet"); 218da6c28aaSamw smb_msgbuf_term(&mb); 219da6c28aaSamw return; 220da6c28aaSamw } 221da6c28aaSamw 222a0aa776eSAlan Wright syslog(LOG_DEBUG, "DC Offer Domain=%s PDC=%s From=%s", 223da6c28aaSamw domain, primary, src_name); 224da6c28aaSamw 2258d7e4166Sjose borrego (void) mutex_lock(&ntdomain_mtx); 2268d7e4166Sjose borrego if (strcasecmp(domain, ntdomain_info.n_domain)) { 227da6c28aaSamw syslog(LOG_DEBUG, "NetLogonResponse: other domain " 2288d7e4166Sjose borrego "%s, requested %s", domain, ntdomain_info.n_domain); 229da6c28aaSamw smb_msgbuf_term(&mb); 2308d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 231da6c28aaSamw return; 232da6c28aaSamw } 2338d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 234da6c28aaSamw 235da6c28aaSamw for (i = 0; i < sizeof (netlogon_opt)/sizeof (netlogon_opt[0]); ++i) { 236da6c28aaSamw if (strcasecmp(netlogon_opt[i].mailslot, mailbox) == 0) { 237da6c28aaSamw syslog(LOG_DEBUG, "NetLogonReceive: %s", mailbox); 238da6c28aaSamw (*netlogon_opt[i].handler)(primary, src_ipaddr); 239da6c28aaSamw smb_msgbuf_term(&mb); 240da6c28aaSamw return; 241da6c28aaSamw } 242da6c28aaSamw } 243da6c28aaSamw 244da6c28aaSamw syslog(LOG_DEBUG, "NetLogonReceive[%s]: unknown mailslot", mailbox); 245da6c28aaSamw smb_msgbuf_term(&mb); 246da6c28aaSamw } 247da6c28aaSamw 248da6c28aaSamw 249da6c28aaSamw 250da6c28aaSamw /* 251da6c28aaSamw * smb_netlogon_query 252da6c28aaSamw * 253da6c28aaSamw * Build and send a LOGON_PRIMARY_QUERY to the MAILSLOT_NETLOGON. At some 254da6c28aaSamw * point we should receive a LOGON_PRIMARY_RESPONSE in the mailslot we 255da6c28aaSamw * specify in the request. 256da6c28aaSamw * 257da6c28aaSamw * struct NETLOGON_QUERY { 258da6c28aaSamw * unsigned short Opcode; # LOGON_PRIMARY_QUERY 259da6c28aaSamw * char ComputerName[]; # ASCII hostname. The response 260da6c28aaSamw * # is sent to <ComputerName>(00). 261da6c28aaSamw * char MailslotName[]; # MAILSLOT_NETLOGON 262da6c28aaSamw * char Pad[]; # Pad to short 263da6c28aaSamw * wchar_t ComputerName[] # UNICODE hostname 264da6c28aaSamw * DWORD NT_Version; # 0x00000001 265da6c28aaSamw * WORD LmNTToken; # 0xffff 266da6c28aaSamw * WORD Lm20Token; # 0xffff 267da6c28aaSamw * }; 268da6c28aaSamw */ 269da6c28aaSamw static void 270da6c28aaSamw smb_netlogon_query(struct name_entry *server, 271da6c28aaSamw char *mailbox, 272da6c28aaSamw char *domain) 273da6c28aaSamw { 274da6c28aaSamw smb_msgbuf_t mb; 275da6c28aaSamw int offset, announce_len, data_length, name_lengths; 276da6c28aaSamw unsigned char buffer[MAX_DATAGRAM_LENGTH]; 277b89a8333Snatalie li - Sun Microsystems - Irvine United States char hostname[NETBIOS_NAME_SZ]; 278da6c28aaSamw 279b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) 280da6c28aaSamw return; 281da6c28aaSamw 282da6c28aaSamw name_lengths = strlen(mailbox)+1+strlen(hostname)+1; 283da6c28aaSamw 284da6c28aaSamw /* 285da6c28aaSamw * The (name_lengths & 1) part is to word align the name_lengths 286da6c28aaSamw * before the wc equiv strlen and the "+ 2" is to cover the two 287da6c28aaSamw * zero bytes that terminate the wchar string. 288da6c28aaSamw */ 289da6c28aaSamw data_length = sizeof (short) + name_lengths + (name_lengths & 1) + 290*bbf6f00cSJordan Brown smb_wcequiv_strlen(hostname) + 2 + sizeof (long) + sizeof (short) + 291da6c28aaSamw sizeof (short); 292da6c28aaSamw 293da6c28aaSamw offset = smb_browser_load_transact_header(buffer, 294da6c28aaSamw sizeof (buffer), data_length, ONE_WAY_TRANSACTION, 295da6c28aaSamw MAILSLOT_NETLOGON); 296da6c28aaSamw 297da6c28aaSamw if (offset < 0) 298da6c28aaSamw return; 299da6c28aaSamw 300da6c28aaSamw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0); 301da6c28aaSamw 302da6c28aaSamw announce_len = smb_msgbuf_encode(&mb, "wssUlww", 303da6c28aaSamw (short)LOGON_PRIMARY_QUERY, 304da6c28aaSamw hostname, 305da6c28aaSamw mailbox, 306da6c28aaSamw hostname, 307da6c28aaSamw 0x1, 308da6c28aaSamw 0xffff, 309da6c28aaSamw 0xffff); 310da6c28aaSamw 311da6c28aaSamw if (announce_len <= 0) { 312da6c28aaSamw smb_msgbuf_term(&mb); 313da6c28aaSamw syslog(LOG_ERR, "NetLogonQuery: encode error"); 314da6c28aaSamw return; 315da6c28aaSamw } 316da6c28aaSamw 317da6c28aaSamw smb_netlogon_send(server, domain, buffer, offset + announce_len); 318da6c28aaSamw smb_msgbuf_term(&mb); 319da6c28aaSamw } 320da6c28aaSamw 321da6c28aaSamw 322da6c28aaSamw /* 323da6c28aaSamw * smb_netlogon_samlogon 324da6c28aaSamw * 325da6c28aaSamw * The SamLogon version of the NetLogon request uses the workstation trust 326da6c28aaSamw * account and, I think, may be a prerequisite to the challenge/response 327da6c28aaSamw * netr authentication. The trust account username is the hostname with a 328da6c28aaSamw * $ appended. The mailslot for this request is MAILSLOT_NTLOGON. At some 329da6c28aaSamw * we should receive a LOGON_SAM_LOGON_RESPONSE in the mailslot we 330da6c28aaSamw * specify in the request. 331da6c28aaSamw * 332da6c28aaSamw * struct NETLOGON_SAM_LOGON { 333da6c28aaSamw * unsigned short Opcode; # LOGON_SAM_LOGON_REQUEST 334da6c28aaSamw * unsigned short RequestCount; # 0 335da6c28aaSamw * wchar_t UnicodeComputerName; # hostname 336da6c28aaSamw * wchar_t UnicodeUserName; # hostname$ 337da6c28aaSamw * char *MailslotName; # response mailslot 338da6c28aaSamw * DWORD AllowableAccountControlBits; # 0x80 = WorkstationTrustAccount 339da6c28aaSamw * DWORD DomainSidSize; # domain sid length in bytes 340da6c28aaSamw * BYTE *DomainSid; # domain sid 341da6c28aaSamw * uint32_t NT_Version; # 0x00000001 342da6c28aaSamw * unsigned short LmNTToken; # 0xffff 343da6c28aaSamw * unsigned short Lm20Token; # 0xffff 344da6c28aaSamw * }; 345da6c28aaSamw */ 346da6c28aaSamw static void 347da6c28aaSamw smb_netlogon_samlogon(struct name_entry *server, 348da6c28aaSamw char *mailbox, 34929bd2886SAlan Wright char *domain, 35029bd2886SAlan Wright smb_sid_t *domain_sid) 351da6c28aaSamw { 352da6c28aaSamw smb_msgbuf_t mb; 353da6c28aaSamw unsigned domain_sid_len; 354da6c28aaSamw char *username; 355da6c28aaSamw unsigned char buffer[MAX_DATAGRAM_LENGTH]; 356da6c28aaSamw int offset; 357da6c28aaSamw int announce_len; 358da6c28aaSamw int data_length; 359da6c28aaSamw int name_length; 360b89a8333Snatalie li - Sun Microsystems - Irvine United States char hostname[NETBIOS_NAME_SZ]; 361da6c28aaSamw 362da6c28aaSamw syslog(LOG_DEBUG, "NetLogonSamLogonReq: %s", domain); 363da6c28aaSamw 364b89a8333Snatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0) 365da6c28aaSamw return; 366da6c28aaSamw 367da6c28aaSamw /* 368da6c28aaSamw * The username will be the trust account name on the PDC. 369da6c28aaSamw */ 370da6c28aaSamw name_length = strlen(hostname) + 2; 371da6c28aaSamw username = alloca(name_length); 372da6c28aaSamw (void) snprintf(username, name_length, "%s$", hostname); 373da6c28aaSamw 37429bd2886SAlan Wright domain_sid_len = smb_sid_len(domain_sid); 375da6c28aaSamw /* 376da6c28aaSamw * Add 2 to wide-char equivalent strlen to cover the 377da6c28aaSamw * two zero bytes that terminate the wchar string. 378da6c28aaSamw */ 379da6c28aaSamw name_length = strlen(mailbox)+1; 380da6c28aaSamw 381da6c28aaSamw data_length = sizeof (short) 382da6c28aaSamw + sizeof (short) 383*bbf6f00cSJordan Brown + smb_wcequiv_strlen(hostname) + 2 384*bbf6f00cSJordan Brown + smb_wcequiv_strlen(username) + 2 385da6c28aaSamw + name_length 386da6c28aaSamw + sizeof (long) 387da6c28aaSamw + sizeof (long) 388da6c28aaSamw + domain_sid_len + 3 /* padding */ 389da6c28aaSamw + sizeof (long) 390da6c28aaSamw + sizeof (short) 391da6c28aaSamw + sizeof (short); 392da6c28aaSamw 393da6c28aaSamw offset = smb_browser_load_transact_header(buffer, 394da6c28aaSamw sizeof (buffer), data_length, ONE_WAY_TRANSACTION, 395da6c28aaSamw MAILSLOT_NTLOGON); 396da6c28aaSamw 397da6c28aaSamw if (offset < 0) { 398da6c28aaSamw syslog(LOG_ERR, "NetLogonSamLogonReq: header error"); 399da6c28aaSamw return; 400da6c28aaSamw } 401da6c28aaSamw 402da6c28aaSamw /* 403da6c28aaSamw * The domain SID is padded with 3 leading zeros. 404da6c28aaSamw */ 405da6c28aaSamw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0); 406da6c28aaSamw announce_len = smb_msgbuf_encode(&mb, "wwUUsll3.#clww", 407da6c28aaSamw (short)LOGON_SAM_LOGON_REQUEST, 408da6c28aaSamw 0, /* RequestCount */ 409da6c28aaSamw hostname, /* UnicodeComputerName */ 410da6c28aaSamw username, /* UnicodeUserName */ 411da6c28aaSamw mailbox, /* MailslotName */ 412da6c28aaSamw 0x00000080, /* AllowableAccountControlBits */ 413da6c28aaSamw domain_sid_len, /* DomainSidSize */ 414da6c28aaSamw domain_sid_len, domain_sid, /* DomainSid */ 415da6c28aaSamw 0x00000001, /* NT_Version */ 416da6c28aaSamw 0xffff, /* LmNTToken */ 417da6c28aaSamw 0xffff); /* Lm20Token */ 418da6c28aaSamw 419da6c28aaSamw if (announce_len <= 0) { 420da6c28aaSamw syslog(LOG_ERR, "NetLogonSamLogonReq: encode error"); 421da6c28aaSamw smb_msgbuf_term(&mb); 422da6c28aaSamw return; 423da6c28aaSamw } 424da6c28aaSamw 425da6c28aaSamw smb_netlogon_send(server, domain, buffer, offset + announce_len); 426da6c28aaSamw smb_msgbuf_term(&mb); 427da6c28aaSamw } 428da6c28aaSamw 429da6c28aaSamw 430da6c28aaSamw /* 431da6c28aaSamw * Send a query for each version of the protocol. 432da6c28aaSamw */ 433da6c28aaSamw static void 434da6c28aaSamw smb_netlogon_send(struct name_entry *name, 435da6c28aaSamw char *domain, 436da6c28aaSamw unsigned char *buffer, 437da6c28aaSamw int count) 438da6c28aaSamw { 439da6c28aaSamw static char suffix[] = { 0x1B, 0x1C }; 440da6c28aaSamw struct name_entry dname; 441da6c28aaSamw struct name_entry *dest; 442da6c28aaSamw struct name_entry *dest_dup; 443da6c28aaSamw int i; 444da6c28aaSamw 445da6c28aaSamw for (i = 0; i < sizeof (suffix)/sizeof (suffix[0]); i++) { 446da6c28aaSamw smb_init_name_struct((unsigned char *)domain, suffix[i], 447da6c28aaSamw 0, 0, 0, 0, 0, &dname); 448da6c28aaSamw 449a0aa776eSAlan Wright syslog(LOG_DEBUG, "SmbNetlogonSend"); 450a0aa776eSAlan Wright smb_netbios_name_logf(&dname); 451da6c28aaSamw if ((dest = smb_name_find_name(&dname)) != 0) { 452da6c28aaSamw dest_dup = smb_netbios_name_dup(dest, 1); 453da6c28aaSamw smb_name_unlock_name(dest); 454da6c28aaSamw if (dest_dup) { 4558d7e4166Sjose borrego (void) smb_netbios_datagram_send(name, 4568d7e4166Sjose borrego dest_dup, buffer, count); 457da6c28aaSamw free(dest_dup); 458da6c28aaSamw } 459da6c28aaSamw } else { 460a0aa776eSAlan Wright syslog(LOG_DEBUG, 461a0aa776eSAlan Wright "SmbNetlogonSend: could not find %s<0x%X>", 462da6c28aaSamw domain, suffix[i]); 463da6c28aaSamw } 464da6c28aaSamw } 465da6c28aaSamw } 466da6c28aaSamw 467da6c28aaSamw /* 468da6c28aaSamw * smb_netlogon_rdc_rsp 469da6c28aaSamw * 470da6c28aaSamw * This is where we process netlogon responses for the resource domain. 471da6c28aaSamw * The src_name is the real name of the remote machine. 472da6c28aaSamw */ 473da6c28aaSamw static void 474da6c28aaSamw smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr) 475da6c28aaSamw { 476da6c28aaSamw static int initialized = 0; 477da6c28aaSamw uint32_t ipaddr; 4787f667e74Sjose borrego uint32_t prefer_ipaddr; 4797f667e74Sjose borrego char ipstr[INET_ADDRSTRLEN]; 4807f667e74Sjose borrego char srcip[INET_ADDRSTRLEN]; 481da6c28aaSamw int rc; 482da6c28aaSamw 4837f667e74Sjose borrego (void) inet_ntop(AF_INET, &src_ipaddr, srcip, INET_ADDRSTRLEN); 484da6c28aaSamw 4857f667e74Sjose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, INET_ADDRSTRLEN); 486dc20a302Sas200622 if (rc == SMBD_SMF_OK) { 487dc20a302Sas200622 rc = inet_pton(AF_INET, ipstr, &prefer_ipaddr); 488da6c28aaSamw if (rc == 0) 489da6c28aaSamw prefer_ipaddr = 0; 490da6c28aaSamw 491da6c28aaSamw if (!initialized) { 492da6c28aaSamw syslog(LOG_DEBUG, "SMB DC Preference: %s", ipstr); 493da6c28aaSamw initialized = 1; 494da6c28aaSamw } 495da6c28aaSamw } 496da6c28aaSamw 4978d7e4166Sjose borrego (void) mutex_lock(&ntdomain_mtx); 498da6c28aaSamw syslog(LOG_DEBUG, "DC Offer [%s]: %s [%s]", 4998d7e4166Sjose borrego ntdomain_info.n_domain, src_name, srcip); 500da6c28aaSamw 5018d7e4166Sjose borrego if (ntdomain_info.n_ipaddr != 0) { 5027f667e74Sjose borrego if (prefer_ipaddr != 0 && 5037f667e74Sjose borrego prefer_ipaddr == ntdomain_info.n_ipaddr) { 504da6c28aaSamw syslog(LOG_DEBUG, "DC for %s: %s [%s]", 5058d7e4166Sjose borrego ntdomain_info.n_domain, src_name, srcip); 5068d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 507da6c28aaSamw return; 508da6c28aaSamw } 509da6c28aaSamw 5108d7e4166Sjose borrego ipaddr = ntdomain_info.n_ipaddr; 511da6c28aaSamw } else 512da6c28aaSamw ipaddr = 0; 513da6c28aaSamw 5143db3f65cSamw if (smb_better_dc(ipaddr, src_ipaddr) || 515da6c28aaSamw (prefer_ipaddr != 0 && prefer_ipaddr == src_ipaddr)) { 5168d7e4166Sjose borrego /* set nbtd cache */ 5178d7e4166Sjose borrego (void) strlcpy(ntdomain_info.n_name, src_name, 5188d7e4166Sjose borrego SMB_PI_MAX_DOMAIN); 5198d7e4166Sjose borrego ntdomain_info.n_ipaddr = src_ipaddr; 5208d7e4166Sjose borrego (void) cond_broadcast(&ntdomain_cv); 521da6c28aaSamw syslog(LOG_DEBUG, "DC discovered for %s: %s [%s]", 5228d7e4166Sjose borrego ntdomain_info.n_domain, src_name, srcip); 523da6c28aaSamw } 5248d7e4166Sjose borrego (void) mutex_unlock(&ntdomain_mtx); 525da6c28aaSamw } 526da6c28aaSamw 527da6c28aaSamw static int 5283db3f65cSamw smb_better_dc(uint32_t cur_ip, uint32_t new_ip) 529da6c28aaSamw { 5307f667e74Sjose borrego smb_inaddr_t ipaddr; 5317f667e74Sjose borrego 532da6c28aaSamw /* 533da6c28aaSamw * If we don't have any current DC, 534da6c28aaSamw * then use the new one of course. 535da6c28aaSamw */ 5367f667e74Sjose borrego 537da6c28aaSamw if (cur_ip == 0) 538da6c28aaSamw return (1); 539fc724630SAlan Wright /* 540fc724630SAlan Wright * see if there is a DC in the 541fc724630SAlan Wright * same subnet 542fc724630SAlan Wright */ 543da6c28aaSamw 5447f667e74Sjose borrego ipaddr.a_family = AF_INET; 5457f667e74Sjose borrego ipaddr.a_ipv4 = cur_ip; 546fc724630SAlan Wright if (smb_nic_is_same_subnet(&ipaddr)) 547da6c28aaSamw return (0); 5487b59d02dSjb150015 5497f667e74Sjose borrego ipaddr.a_family = AF_INET; 5507f667e74Sjose borrego ipaddr.a_ipv4 = new_ip; 551fc724630SAlan Wright if (smb_nic_is_same_subnet(&ipaddr)) 552da6c28aaSamw return (1); 553da6c28aaSamw /* 554da6c28aaSamw * Otherwise, just keep the old one. 555da6c28aaSamw */ 556da6c28aaSamw return (0); 557da6c28aaSamw } 558