da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This module handles the primary domain controller location protocol.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The document claims to be version 1.15 of the browsing protocol. It also
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * claims to specify the mailslot protocol.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The NETLOGON protocol uses \MAILSLOT\NET mailslots. The protocol
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specification is incomplete, contains errors and is out-of-date but
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * it does provide some useful background information. The document
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * doesn't mention the NETLOGON_SAMLOGON version of the protocol.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smb_netlogon_query(struct name_entry *server, char *mailbox,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstatic void smb_netlogon_samlogon(struct name_entry *, char *,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smb_netlogon_send(struct name_entry *name, char *domain,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr);
3db3f65c6274eb042354801a308c8e9bc4994553amwstatic int smb_better_dc(uint32_t cur_ip, uint32_t new_ip);
8d7e41661dc4633488e93b13363137523ce59977jose borrego * ntdomain_info
8d7e41661dc4633488e93b13363137523ce59977jose borrego * Temporary. It should be removed once NBTD is integrated.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_request
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is the entry point locating the resource domain PDC. A netlogon
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * request is sent using the specified protocol on the specified network.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Note that we need to know the domain SID in order to use the samlogon
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Netlogon responses are received asynchronously and eventually handled
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in smb_netlogon_receive.
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightsmb_netlogon_request(struct name_entry *server, char *domain)
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright smb_config_getdomaininfo(di.di_nbname, NULL, di.di_sid, NULL, NULL);
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if (smb_strcasecmp(di.di_nbname, domain, 0) == 0) {
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright smb_netlogon_samlogon(server, MAILSLOT_NETLOGON_SAMLOGON_RDC,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright smb_netlogon_query(server, MAILSLOT_NETLOGON_RDC, domain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_receive
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is where we handle all incoming NetLogon messages. Currently, we
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ignore requests from anyone else. We are only interested in responses
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to our own requests. The NetLogonResponse provides the name of the PDC.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If we don't already have a controller name, we use the name provided
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * in the message. Otherwise we use the name already in the environment.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *data,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw { MAILSLOT_NETLOGON_SAMLOGON_RDC, smb_netlogon_rdc_rsp },
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw src_ipaddr = datagram->src.addr_list.sin.sin_addr.s_addr;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The datagram->src.name is in oem codepage format.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Therefore, we need to convert it to unicode and
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * store it in multi-bytes format.
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown (void) oemtoucs(unicode_src_name, (char *)datagram->src.name,
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown (void) smb_wcstombs(src_name, unicode_src_name, SMB_PI_MAX_HOST);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr), ipstr,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (ipstr));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "NetLogonReceive: src=%s [%s], mbx=%s",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Message contains:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * PDC name (MBS), PDC name (Unicode), Domain name (unicode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_msgbuf_decode(&mb, "sUU", &junk, &primary, &domain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "NetLogonResponse: opcode %d decode error",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Message contains:
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * PDC name, User name, Domain name (all unicode)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rc = smb_msgbuf_decode(&mb, "UUU", &primary, &junk, &domain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (rc < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw "NetLogonResponse: opcode %d decode error",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * skip past the "\\" prefix
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We don't respond to PDC discovery requests.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "NetLogonReceive: opcode 0x%04x", opcode);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright syslog(LOG_DEBUG, "DC Offer Domain=%s PDC=%s From=%s",
8d7e41661dc4633488e93b13363137523ce59977jose borrego if (strcasecmp(domain, ntdomain_info.n_domain)) {
8d7e41661dc4633488e93b13363137523ce59977jose borrego "%s, requested %s", domain, ntdomain_info.n_domain);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < sizeof (netlogon_opt)/sizeof (netlogon_opt[0]); ++i) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (strcasecmp(netlogon_opt[i].mailslot, mailbox) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw syslog(LOG_DEBUG, "NetLogonReceive[%s]: unknown mailslot", mailbox);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_query
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Build and send a LOGON_PRIMARY_QUERY to the MAILSLOT_NETLOGON. At some
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * point we should receive a LOGON_PRIMARY_RESPONSE in the mailslot we
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specify in the request.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct NETLOGON_QUERY {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned short Opcode; # LOGON_PRIMARY_QUERY
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * char ComputerName[]; # ASCII hostname. The response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * # is sent to <ComputerName>(00).
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * char MailslotName[]; # MAILSLOT_NETLOGON
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * char Pad[]; # Pad to short
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wchar_t ComputerName[] # UNICODE hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * DWORD NT_Version; # 0x00000001
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * WORD LmNTToken; # 0xffff
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * WORD Lm20Token; # 0xffff
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States char hostname[NETBIOS_NAME_SZ];
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The (name_lengths & 1) part is to word align the name_lengths
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * before the wc equiv strlen and the "+ 2" is to cover the two
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * zero bytes that terminate the wchar string.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_length = sizeof (short) + name_lengths + (name_lengths & 1) +
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wcequiv_strlen(hostname) + 2 + sizeof (long) + sizeof (short) +
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw sizeof (short);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netlogon_send(server, domain, buffer, offset + announce_len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_samlogon
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The SamLogon version of the NetLogon request uses the workstation trust
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * account and, I think, may be a prerequisite to the challenge/response
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * netr authentication. The trust account username is the hostname with a
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * $ appended. The mailslot for this request is MAILSLOT_NTLOGON. At some
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * we should receive a LOGON_SAM_LOGON_RESPONSE in the mailslot we
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * specify in the request.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * struct NETLOGON_SAM_LOGON {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned short Opcode; # LOGON_SAM_LOGON_REQUEST
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned short RequestCount; # 0
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wchar_t UnicodeComputerName; # hostname
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wchar_t UnicodeUserName; # hostname$
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * char *MailslotName; # response mailslot
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * DWORD AllowableAccountControlBits; # 0x80 = WorkstationTrustAccount
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * DWORD DomainSidSize; # domain sid length in bytes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * BYTE *DomainSid; # domain sid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * uint32_t NT_Version; # 0x00000001
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned short LmNTToken; # 0xffff
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * unsigned short Lm20Token; # 0xffff
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States char hostname[NETBIOS_NAME_SZ];
b89a8333f5e1f75ec0c269b22524bd2eccb972banatalie li - Sun Microsystems - Irvine United States if (smb_getnetbiosname(hostname, sizeof (hostname)) != 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The username will be the trust account name on the PDC.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) snprintf(username, name_length, "%s$", hostname);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Add 2 to wide-char equivalent strlen to cover the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * two zero bytes that terminate the wchar string.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw data_length = sizeof (short)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (short)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (long)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (long)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (long)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (short)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw + sizeof (short);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The domain SID is padded with 3 leading zeros.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_msgbuf_init(&mb, buffer + offset, sizeof (buffer) - offset, 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, /* RequestCount */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_netlogon_send(server, domain, buffer, offset + announce_len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Send a query for each version of the protocol.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *buffer,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw for (i = 0; i < sizeof (suffix)/sizeof (suffix[0]); i++) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw smb_init_name_struct((unsigned char *)domain, suffix[i],
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw 0, 0, 0, 0, 0, &dname);
a0aa776e20803c84edd153d9cb584fd67163aef3Alan Wright "SmbNetlogonSend: could not find %s<0x%X>",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * smb_netlogon_rdc_rsp
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * This is where we process netlogon responses for the resource domain.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The src_name is the real name of the remote machine.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsmb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr)
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego (void) inet_ntop(AF_INET, &src_ipaddr, srcip, INET_ADDRSTRLEN);
7f667e74610492ddbce8ce60f52ece95d2401949jose borrego rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, INET_ADDRSTRLEN);
8d7e41661dc4633488e93b13363137523ce59977jose borrego /* set nbtd cache */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If we don't have any current DC,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * then use the new one of course.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright * see if there is a DC in the
fc724630b14603e4c1147df68b7bf45f7de7431fAlan Wright * same subnet
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Otherwise, just keep the old one.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);