# HG changeset patch # User Alan Wright # Date 1254765814 25200 # Node ID fe0545fc3cdd0264ac2a5fa8b186699397e3ed58 # Parent b17df522be57617998e50242a9438ae169cdeb38 6612607 CIFS ADS client should use ldap_sasl_interactive_bind_s API 6877755 smbd should not route stderr, stdout to /dev/null 6882701 Wrong error message for attempt to map local user to Windows group, or vice versa 6885105 Potential for deadlock in smb_node_set_delete_on_close() 6881928 smbd core generated when running a script to join domain, set abe properties 6885538 Reduce dependencies on libsmbrdr 6820325 cifs service can't start on multi vlan+ipmp configuration diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/idmap/idmapd/dbutils.c --- a/usr/src/cmd/idmap/idmapd/dbutils.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/idmap/idmapd/dbutils.c Mon Oct 05 11:03:34 2009 -0700 @@ -2572,9 +2572,9 @@ * way we generate localSIDs. */ if (is_user && res->id.idtype == IDMAP_GSID) - return (IDMAP_ERR_NOMAPPING); + return (IDMAP_ERR_NOTGROUP); if (!is_user && res->id.idtype == IDMAP_USID) - return (IDMAP_ERR_NOMAPPING); + return (IDMAP_ERR_NOTUSER); /* Skip 1000 UIDs */ if (is_user && diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbadm/smbadm.c --- a/usr/src/cmd/smbsrv/smbadm/smbadm.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c Mon Oct 05 11:03:34 2009 -0700 @@ -817,7 +817,7 @@ srvname, fqdn, ipstr); } - nt_domain_show(); + smb_domain_show(); return (0); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/Makefile --- a/usr/src/cmd/smbsrv/smbd/Makefile Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/Makefile Mon Oct 05 11:03:34 2009 -0700 @@ -47,7 +47,7 @@ include ../Makefile.smbsrv.defs -LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbrdr -lsmbns -lsmb \ +LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbns -lsmb \ -lzfs -lbsm -lnsl -lumem LDFLAGS += -R/usr/lib/smbsrv diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/smbd_door_ops.c --- a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c Mon Oct 05 11:03:34 2009 -0700 @@ -299,17 +299,17 @@ door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) { char *rbuf = NULL; - smb_domain_t dinfo; + smb_domainex_t dxi; *err = SMB_DR_OP_SUCCESS; *rbufsize = 0; - if (!smb_domain_getinfo(&dinfo)) { + if (!smb_domain_getinfo(&dxi)) { *err = SMB_DR_OP_ERR_EMPTYBUF; return (NULL); } - if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, dinfo.d_dc, + if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, dxi.d_dc, rbufsize)) == NULL) { *err = SMB_DR_OP_ERR_ENCODE; *rbufsize = 0; diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c --- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * SMBd door server */ @@ -178,8 +176,6 @@ goto door_return; } - syslog(LOG_DEBUG, "smb_door_srv_func: execute server routine" - "(opcode=%d)", opcode); if (smb_dr_is_valid_opcode(opcode) != 0) { tmpbuf = smb_door_srv_err_hdlr(SMB_DR_OP_ERR_INVALID_OPCODE, &rbufsize); diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/smbd_join.c --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c Mon Oct 05 11:03:34 2009 -0700 @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -81,7 +80,7 @@ * * Since the kclient has updated the machine password stored in SMF * repository, the cached ipc_info must be updated accordingly by calling - * smbrdr_ipc_commit. + * smb_ipc_commit. * * Due to potential replication delays in a multiple DC environment, the * NETLOGON rpc request must be sent to the DC, to which the KPASSWD request @@ -99,10 +98,11 @@ char kpasswd_srv[MAXHOSTNAMELEN]; char kpasswd_domain[MAXHOSTNAMELEN]; char sam_acct[SMB_SAMACCT_MAXLEN]; - char *ipc_usr, *dom; + char ipc_usr[SMB_USERNAME_MAXLEN]; + char *dom; boolean_t new_domain = B_FALSE; - smb_domain_t domain; - nt_domain_t *di; + smb_domainex_t dxi; + smb_domain_t *di; if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) return (B_FALSE); @@ -121,12 +121,12 @@ * progress, don't do anything. */ (void) smb_getsamaccount(sam_acct, sizeof (sam_acct)); - ipc_usr = smbrdr_ipc_get_user(); + smb_ipc_get_user(ipc_usr, SMB_USERNAME_MAXLEN); if (utf8_strcasecmp(ipc_usr, sam_acct)) return (B_FALSE); - di = &domain.d_info; - if (!smb_domain_getinfo(&domain)) + di = &dxi.d_primary; + if (!smb_domain_getinfo(&dxi)) (void) smb_getfqdomainname(di->di_fqname, MAXHOSTNAMELEN); (void) smb_config_getstr(SMB_CI_KPASSWD_DOMAIN, kpasswd_domain, @@ -145,20 +145,20 @@ * currently cached or the SMB daemon has previously discovered a DC * that is different than the kpasswd server. */ - if (new_domain || utf8_strcasecmp(domain.d_dc, kpasswd_srv) != 0) { - if (*domain.d_dc != '\0') - mlsvc_disconnect(domain.d_dc); + if (new_domain || utf8_strcasecmp(dxi.d_dc, kpasswd_srv) != 0) { + if (*dxi.d_dc != '\0') + mlsvc_disconnect(dxi.d_dc); - if (!smb_locate_dc(dom, kpasswd_srv, &domain)) { - if (!smb_locate_dc(di->di_fqname, "", &domain)) { - smbrdr_ipc_commit(); + if (!smb_locate_dc(dom, kpasswd_srv, &dxi)) { + if (!smb_locate_dc(di->di_fqname, "", &dxi)) { + smb_ipc_commit(); return (B_FALSE); } } } - smbrdr_ipc_commit(); - if (mlsvc_netlogon(domain.d_dc, di->di_nbname)) { + smb_ipc_commit(); + if (mlsvc_netlogon(dxi.d_dc, di->di_nbname)) { syslog(LOG_ERR, "failed to establish NETLOGON credential chain"); return (B_TRUE); @@ -209,8 +209,8 @@ smbd_locate_dc_thread(void *arg) { char domain[MAXHOSTNAMELEN]; - smb_domain_t new_domain; - nt_domain_t *di; + smb_domainex_t new_domain; + smb_domain_t *di; if (!smb_match_netlogon_seqnum()) { (void) smbd_set_netlogon_cred(); @@ -221,7 +221,7 @@ } if (smb_locate_dc(domain, "", &new_domain)) { - di = &new_domain.d_info; + di = &new_domain.d_primary; smb_config_setdomaininfo(di->di_nbname, di->di_fqname, di->di_sid, di->di_u.di_dns.ddi_forest, @@ -298,8 +298,8 @@ uint32_t status; unsigned char passwd_hash[SMBAUTH_HASH_SZ]; char dc[MAXHOSTNAMELEN]; - smb_domain_t domain_info; - nt_domain_t *di; + smb_domainex_t dxi; + smb_domain_t *di; /* * Ensure that any previous membership of this domain has @@ -317,32 +317,32 @@ return (NT_STATUS_INTERNAL_ERROR); } - smbrdr_ipc_set(info->domain_username, passwd_hash); + smb_ipc_set(info->domain_username, passwd_hash); (void) smbd_get_kpasswd_srv(dc, sizeof (dc)); /* info->domain_name could either be NetBIOS domain name or FQDN */ - if (smb_locate_dc(info->domain_name, dc, &domain_info)) { - status = mlsvc_join(&domain_info, info->domain_username, + if (smb_locate_dc(info->domain_name, dc, &dxi)) { + status = mlsvc_join(&dxi, info->domain_username, info->domain_passwd); if (status == NT_STATUS_SUCCESS) { - di = &domain_info.d_info; + di = &dxi.d_primary; smbd_set_secmode(SMB_SECMODE_DOMAIN); smb_config_setdomaininfo(di->di_nbname, di->di_fqname, di->di_sid, di->di_u.di_dns.ddi_forest, di->di_u.di_dns.ddi_guid); - smbrdr_ipc_commit(); + smb_ipc_commit(); return (status); } - smbrdr_ipc_rollback(); + smb_ipc_rollback(); syslog(LOG_ERR, "smbd: failed joining %s (%s)", info->domain_name, xlate_nt_status(status)); return (status); } - smbrdr_ipc_rollback(); + smb_ipc_rollback(); syslog(LOG_ERR, "smbd: failed locating domain controller for %s", info->domain_name); return (NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND); diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/smbd_main.c --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c Mon Oct 05 11:03:34 2009 -0700 @@ -54,7 +54,6 @@ #include #include #include -#include #include #include "smbd.h" @@ -387,13 +386,6 @@ (void) close(fd); - if ((fd = open("/dev/null", O_RDWR)) >= 0) { - (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); - (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); - (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); - (void) close(fd); - } - pset = priv_allocset(); if (pset == NULL) return; @@ -453,7 +445,7 @@ smbd_report("NIC monitoring failed to start"); (void) dyndns_start(); - smbrdr_init(); + smb_ipc_init(); if (smb_netbios_start() != 0) smbd_report("NetBIOS services failed to start"); @@ -467,7 +459,7 @@ } smbd.s_secmode = smb_config_get_secmode(); - if ((rc = nt_domain_init(smbd.s_secmode)) != 0) { + if ((rc = smb_domain_init(smbd.s_secmode)) != 0) { if (rc == SMB_DOMAIN_NOMACHINE_SID) { smbd_report( "no machine SID: check idmap configuration"); @@ -552,9 +544,10 @@ smb_lgrp_stop(); smb_ccache_remove(SMB_CCACHE_PATH); smb_pwd_fini(); - nt_domain_fini(); + smb_domain_fini(); mlsvc_fini(); smb_ads_fini(); + smb_netbios_stop(); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/cmd/smbsrv/smbd/smbd_vss.c --- a/usr/src/cmd/smbsrv/smbd/smbd_vss.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/cmd/smbsrv/smbd/smbd_vss.c Mon Oct 05 11:03:34 2009 -0700 @@ -32,7 +32,6 @@ #include #include -#include #include #include #include diff -r b17df522be57 -r fe0545fc3cdd usr/src/common/smbsrv/smb_native.c --- a/usr/src/common/smbsrv/smb_native.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/common/smbsrv/smb_native.c Mon Oct 05 11:03:34 2009 -0700 @@ -79,8 +79,6 @@ { NATIVE_OS_WIN95, "Windows 4.0" }, { NATIVE_OS_WIN2000, "Windows 5.0" }, { NATIVE_OS_WIN2000, "Windows 5.1" }, - { NATIVE_OS_WIN2000, "Windows 2000 5.0" }, - { NATIVE_OS_NT5_1, "Windows 2000 5.1" }, { NATIVE_OS_WIN2000, "Windows 2000" }, { NATIVE_OS_WIN2000, "Windows 2002" }, { NATIVE_OS_WIN2000, "Windows .NET" }, diff -r b17df522be57 -r fe0545fc3cdd usr/src/common/smbsrv/smb_sid.c --- a/usr/src/common/smbsrv/smb_sid.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/common/smbsrv/smb_sid.c Mon Oct 05 11:03:34 2009 -0700 @@ -265,10 +265,10 @@ boolean_t smb_sid_islocal(smb_sid_t *sid) { - nt_domain_t di; + smb_domain_t di; boolean_t islocal = B_FALSE; - if (nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di)) + if (smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) islocal = smb_sid_indomain(di.di_binsid, sid); return (islocal); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c --- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1186,10 +1186,8 @@ if (ti == &ndt_s_wchar) { /* - * size_is is the number of characters in the string, - * including the null. We assume valp is UTF-8 encoded. - * We can use mts_wcequiv_strlen for ASCII, extended - * ASCII or Unicode (UCS-2). + * size_is is the number of characters in the + * (multibyte) string, including the null. */ size_is = (mts_wcequiv_strlen(valp) / sizeof (mts_wchar_t)) + 1; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c --- a/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/dssetup_clnt.c Mon Oct 05 11:03:34 2009 -0700 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -40,7 +39,7 @@ { dssetup_DsRoleGetPrimaryDomainInfo_t arg; struct dssetup_DsRolePrimaryDomInfo1 *info; - smb_domain_t di; + smb_domainex_t di; mlsvc_handle_t handle; int opnum; int rc; @@ -48,7 +47,7 @@ if (!smb_domain_getinfo(&di)) return (-1); - if (ndr_rpc_bind(&handle, di.d_dc, di.d_info.di_nbname, + if (ndr_rpc_bind(&handle, di.d_dc, di.d_primary.di_nbname, MLSVC_ANON_USER, "DSSETUP") != 0) return (-1); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Mon Oct 05 11:03:34 2009 -0700 @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -58,15 +57,15 @@ * information. */ -extern boolean_t smb_locate_dc(char *, char *, smb_domain_t *); -extern boolean_t smb_domain_getinfo(smb_domain_t *); - +extern boolean_t smb_locate_dc(char *, char *, smb_domainex_t *); extern void dssetup_clear_domain_info(void); +extern void mlsvc_disconnect(const char *); extern int mlsvc_init(void); extern void mlsvc_fini(void); +extern int mlsvc_ping(const char *); extern DWORD mlsvc_netlogon(char *, char *); -extern DWORD mlsvc_join(smb_domain_t *, char *, char *); +extern DWORD mlsvc_join(smb_domainex_t *, char *, char *); /* @@ -136,6 +135,7 @@ uint32_t sv_version_minor; uint32_t sv_type; char *sv_comment; + uint32_t sv_os; } srvsvc_server_info_t; int srvsvc_net_server_getinfo(char *, char *, srvsvc_server_info_t *); @@ -151,16 +151,16 @@ typedef struct mlsvc_handle { ndr_hdid_t handle; ndr_client_t *clnt; - int remote_os; + uint32_t remote_os; srvsvc_server_info_t svinfo; } mlsvc_handle_t; +void ndr_rpc_init(void); +void ndr_rpc_fini(void); int ndr_rpc_bind(mlsvc_handle_t *, char *, char *, char *, const char *); void ndr_rpc_unbind(mlsvc_handle_t *); int ndr_rpc_call(mlsvc_handle_t *, int, void *); -void ndr_rpc_server_setinfo(mlsvc_handle_t *, const srvsvc_server_info_t *); -void ndr_rpc_server_getinfo(mlsvc_handle_t *, srvsvc_server_info_t *); -int ndr_rpc_server_os(mlsvc_handle_t *); +uint32_t ndr_rpc_server_os(mlsvc_handle_t *); int ndr_rpc_get_ssnkey(mlsvc_handle_t *, unsigned char *, size_t); void *ndr_rpc_malloc(mlsvc_handle_t *, size_t); ndr_heap_t *ndr_rpc_get_heap(mlsvc_handle_t *); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/lsalib.c --- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c Mon Oct 05 11:03:34 2009 -0700 @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -139,11 +138,13 @@ */ DWORD lsa_query_primary_domain_info(char *server, char *domain, - nt_domain_t *info) + smb_domain_t *info) { mlsvc_handle_t domain_handle; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if ((lsar_open(server, domain, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -165,11 +166,13 @@ */ DWORD lsa_query_account_domain_info(char *server, char *domain, - nt_domain_t *info) + smb_domain_t *info) { mlsvc_handle_t domain_handle; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if ((lsar_open(server, domain, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -192,11 +195,13 @@ * Returns NT status codes. */ DWORD -lsa_query_dns_domain_info(char *server, char *domain, nt_domain_t *info) +lsa_query_dns_domain_info(char *server, char *domain, smb_domain_t *info) { mlsvc_handle_t domain_handle; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if ((lsar_open(server, domain, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -224,7 +229,9 @@ mlsvc_handle_t domain_handle; DWORD enum_context; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if ((lsar_open(server, domain, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -261,7 +268,9 @@ mlsvc_handle_t domain_handle; DWORD enum_context; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if ((lsar_open(server, domain, user, &domain_handle)) != 0) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -335,14 +344,16 @@ lsa_lookup_name_domain(char *account_name, smb_account_t *info) { mlsvc_handle_t domain_handle; - smb_domain_t dinfo; - char *user = smbrdr_ipc_get_user(); + smb_domainex_t dinfo; uint32_t status; + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (!smb_domain_getinfo(&dinfo)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - if (lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user, + if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user, &domain_handle) != 0) return (NT_STATUS_INVALID_PARAMETER); @@ -378,13 +389,15 @@ { mlsvc_handle_t domain_handle; int rc; - char *user = smbrdr_ipc_get_user(); - smb_domain_t dinfo; + smb_domainex_t dinfo; + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (!smb_domain_getinfo(&dinfo)) return (-1); - if ((lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user, + if ((lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user, &domain_handle)) != 0) return (-1); @@ -409,7 +422,9 @@ mlsvc_handle_t domain_handle; int rc; int i; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = lsar_open(server, domain, user, &domain_handle); if (rc != 0) @@ -519,14 +534,16 @@ lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo) { mlsvc_handle_t domain_handle; - char *user = smbrdr_ipc_get_user(); uint32_t status; - smb_domain_t dinfo; + smb_domainex_t dinfo; + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (!smb_domain_getinfo(&dinfo)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - if (lsar_open(dinfo.d_dc, dinfo.d_info.di_nbname, user, + if (lsar_open(dinfo.d_dc, dinfo.d_primary.di_nbname, user, &domain_handle) != 0) return (NT_STATUS_INVALID_PARAMETER); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/lsalib.h --- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h Mon Oct 05 11:03:34 2009 -0700 @@ -50,9 +50,9 @@ */ uint32_t lsa_lookup_name(char *, uint16_t, smb_account_t *); uint32_t lsa_lookup_sid(smb_sid_t *, smb_account_t *); -DWORD lsa_query_primary_domain_info(char *, char *, nt_domain_t *); -DWORD lsa_query_account_domain_info(char *, char *, nt_domain_t *); -DWORD lsa_query_dns_domain_info(char *, char *, nt_domain_t *); +DWORD lsa_query_primary_domain_info(char *, char *, smb_domain_t *); +DWORD lsa_query_account_domain_info(char *, char *, smb_domain_t *); +DWORD lsa_query_dns_domain_info(char *, char *, smb_domain_t *); DWORD lsa_enum_trusted_domains(char *, char *, smb_trusted_domains_t *); DWORD lsa_enum_trusted_domains_ex(char *, char *, smb_trusted_domains_t *); @@ -68,7 +68,7 @@ * lsar_lookup.c */ int lsar_query_security_desc(mlsvc_handle_t *); -DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, nt_domain_t *); +DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, smb_domain_t *); uint32_t lsar_lookup_names(mlsvc_handle_t *, char *, smb_account_t *); uint32_t lsar_lookup_names2(mlsvc_handle_t *, char *, smb_account_t *); uint32_t lsar_lookup_sids(mlsvc_handle_t *, struct mslsa_sid *, diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c Mon Oct 05 11:03:34 2009 -0700 @@ -103,7 +103,7 @@ */ DWORD lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass, - nt_domain_t *info) + smb_domain_t *info) { struct mslsa_QueryInfoPolicy arg; struct mslsa_PrimaryDomainInfo *pd_info; @@ -119,7 +119,7 @@ opnum = LSARPC_OPNUM_QueryInfoPolicy; - bzero(info, sizeof (nt_domain_t)); + bzero(info, sizeof (smb_domain_t)); bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy)); (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); @@ -137,8 +137,8 @@ pd_info = &arg.ru.pd_info; smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr); - info->di_type = NT_DOMAIN_PRIMARY; - nt_domain_set_basic_info(sidstr, + info->di_type = SMB_DOMAIN_PRIMARY; + smb_domain_set_basic_info(sidstr, (char *)pd_info->name.str, "", info); status = NT_STATUS_SUCCESS; @@ -148,8 +148,8 @@ ad_info = &arg.ru.ad_info; smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr); - info->di_type = NT_DOMAIN_ACCOUNT; - nt_domain_set_basic_info(sidstr, + info->di_type = SMB_DOMAIN_ACCOUNT; + smb_domain_set_basic_info(sidstr, (char *)ad_info->name.str, "", info); status = NT_STATUS_SUCCESS; @@ -161,8 +161,8 @@ guid_str); smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr); - info->di_type = NT_DOMAIN_PRIMARY; - nt_domain_set_dns_info(sidstr, + info->di_type = SMB_DOMAIN_PRIMARY; + smb_domain_set_dns_info(sidstr, (char *)dns_info->nb_domain.str, (char *)dns_info->dns_domain.str, (char *)dns_info->forest.str, @@ -884,7 +884,8 @@ return; list->td_num = 0; - list->td_domains = calloc(enum_buf->entries_read, sizeof (nt_domain_t)); + list->td_domains = calloc(enum_buf->entries_read, + sizeof (smb_domain_t)); if (list->td_domains == NULL) return; @@ -892,7 +893,7 @@ list->td_num = enum_buf->entries_read; for (i = 0; i < list->td_num; i++) { smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); - nt_domain_set_trust_info( + smb_domain_set_trust_info( sidstr, (char *)enum_buf->info[i].nb_name.str, (char *)enum_buf->info[i].dns_name.str, @@ -914,7 +915,8 @@ return; list->td_num = 0; - list->td_domains = calloc(enum_buf->entries_read, sizeof (nt_domain_t)); + list->td_domains = calloc(enum_buf->entries_read, + sizeof (smb_domain_t)); if (list->td_domains == NULL) return; @@ -922,7 +924,7 @@ list->td_num = enum_buf->entries_read; for (i = 0; i < list->td_num; i++) { smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr); - nt_domain_set_trust_info( + smb_domain_set_trust_info( sidstr, (char *)enum_buf->info[i].name.str, "", 0, 0, 0, &list->td_domains[i]); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_open.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -104,7 +103,7 @@ (void) snprintf((char *)arg.servername, len, "\\\\%s", server); arg.attributes.length = sizeof (struct mslsa_object_attributes); - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_NT5_0) { + if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) { arg.desiredAccess = MAXIMUM_ALLOWED; } else { arg.desiredAccess = GENERIC_EXECUTE diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Mon Oct 05 11:03:34 2009 -0700 @@ -41,6 +41,7 @@ SUNWprivate { global: dssetup_clear_domain_info; + mlsvc_disconnect; mlsvc_fini; mlsvc_init; mlsvc_join; @@ -49,7 +50,6 @@ mlsvc_netlogon; smb_autohome_add; smb_autohome_remove; - smb_domain_getinfo; smb_locate_dc; smb_logon; smb_shr_add; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c Mon Oct 05 11:03:34 2009 -0700 @@ -27,14 +27,39 @@ * Client NDR RPC interface. */ +#include #include +#include #include #include +#include +#include #include #include #include #include +/* + * Server info cache entry expiration in seconds. + */ +#define NDR_SVINFO_TIMEOUT 1800 + +typedef struct ndr_svinfo { + list_node_t svi_lnd; + time_t svi_tcached; + char svi_server[MAXNAMELEN]; + char svi_domain[MAXNAMELEN]; + srvsvc_server_info_t svi_svinfo; +} ndr_svinfo_t; + +typedef struct ndr_svlist { + list_t svl_list; + mutex_t svl_mtx; + boolean_t svl_init; +} ndr_svlist_t; + +static ndr_svlist_t ndr_svlist; + static int ndr_xa_init(ndr_client_t *, ndr_xa_t *); static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *); static int ndr_xa_read(ndr_client_t *, ndr_xa_t *); @@ -42,6 +67,54 @@ static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *); static void ndr_xa_release(ndr_client_t *); +static int ndr_svinfo_lookup(char *, char *, srvsvc_server_info_t *); +static boolean_t ndr_svinfo_match(const char *, const char *, const + ndr_svinfo_t *); +static boolean_t ndr_svinfo_expired(ndr_svinfo_t *); + +/* + * Initialize the RPC client interface: create the server info cache. + */ +void +ndr_rpc_init(void) +{ + (void) mutex_lock(&ndr_svlist.svl_mtx); + + if (!ndr_svlist.svl_init) { + list_create(&ndr_svlist.svl_list, sizeof (ndr_svinfo_t), + offsetof(ndr_svinfo_t, svi_lnd)); + ndr_svlist.svl_init = B_TRUE; + } + + (void) mutex_unlock(&ndr_svlist.svl_mtx); +} + +/* + * Terminate the RPC client interface: flush and destroy the server info + * cache. + */ +void +ndr_rpc_fini(void) +{ + ndr_svinfo_t *svi; + + (void) mutex_lock(&ndr_svlist.svl_mtx); + + if (ndr_svlist.svl_init) { + while ((svi = list_head(&ndr_svlist.svl_list)) != NULL) { + list_remove(&ndr_svlist.svl_list, svi); + free(svi->svi_svinfo.sv_name); + free(svi->svi_svinfo.sv_comment); + free(svi); + } + + list_destroy(&ndr_svlist.svl_list); + ndr_svlist.svl_init = B_FALSE; + } + + (void) mutex_unlock(&ndr_svlist.svl_mtx); +} + /* * This call must be made to initialize an RPC client structure and bind * to the remote service before any RPCs can be exchanged with that service. @@ -61,7 +134,8 @@ { ndr_client_t *clnt; ndr_service_t *svc; - smbrdr_session_info_t si; + srvsvc_server_info_t svinfo; + int remote_os; int fid; int rc; @@ -72,6 +146,20 @@ if ((svc = ndr_svc_lookup_name(service)) == NULL) return (-1); + /* + * Set the default based on the assumption that most + * servers will be Windows 2000 or later. + * Don't lookup the svinfo if this is a SRVSVC request + * because the SRVSVC is used to get the server info. + * None of the SRVSVC calls depend on the remote OS. + */ + remote_os = NATIVE_OS_WIN2000; + + if (strcasecmp(service, "SRVSVC") != 0) { + if (ndr_svinfo_lookup(server, domain, &svinfo) == 0) + remote_os = svinfo.sv_os; + } + if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) return (-1); @@ -95,10 +183,9 @@ clnt->xa_destruct = ndr_xa_destruct; clnt->xa_release = ndr_xa_release; - (void) smbrdr_session_info(fid, &si); bzero(&handle->handle, sizeof (ndr_hdid_t)); handle->clnt = clnt; - handle->remote_os = si.si_server_os; + handle->remote_os = remote_os; if (ndr_rpc_get_heap(handle) == NULL) { free(clnt); @@ -170,39 +257,9 @@ } /* - * Set information about the remote RPC server in the handle. - */ -void -ndr_rpc_server_setinfo(mlsvc_handle_t *handle, - const srvsvc_server_info_t *svinfo) -{ - bcopy(svinfo, &handle->svinfo, sizeof (srvsvc_server_info_t)); - handle->svinfo.sv_name = NULL; - handle->svinfo.sv_comment = NULL; - - if (svinfo->sv_version_major > 4) - handle->remote_os = NATIVE_OS_WIN2000; - else - handle->remote_os = NATIVE_OS_WINNT; - - smb_tracef("NdrRpcServerSetInfo: %s (version %d.%d)", - svinfo->sv_name ? svinfo->sv_name : "", - svinfo->sv_version_major, svinfo->sv_version_minor); -} - -/* - * Get information about the remote RPC server from the handle. - */ -void -ndr_rpc_server_getinfo(mlsvc_handle_t *handle, srvsvc_server_info_t *svinfo) -{ - bcopy(&handle->svinfo, svinfo, sizeof (srvsvc_server_info_t)); -} - -/* * Returns the Native-OS of the RPC server. */ -int +uint32_t ndr_rpc_server_os(mlsvc_handle_t *handle) { return (handle->remote_os); @@ -468,3 +525,90 @@ clnt->heap_preserved = B_FALSE; } } + +/* + * Lookup platform, type and version information about a server. + * If the cache doesn't already contain the data, contact the server and + * cache the response before returning the server info to the caller. + */ +static int +ndr_svinfo_lookup(char *server, char *domain, srvsvc_server_info_t *svinfo) +{ + ndr_svinfo_t *svi; + + (void) mutex_lock(&ndr_svlist.svl_mtx); + assert(ndr_svlist.svl_init == B_TRUE); + + svi = list_head(&ndr_svlist.svl_list); + while (svi != NULL) { + if (ndr_svinfo_expired(svi)) { + svi = list_head(&ndr_svlist.svl_list); + continue; + } + + if (ndr_svinfo_match(server, domain, svi)) { + bcopy(&svi->svi_svinfo, svinfo, + sizeof (srvsvc_server_info_t)); + (void) mutex_unlock(&ndr_svlist.svl_mtx); + return (0); + } + + svi = list_next(&ndr_svlist.svl_list, svi); + } + + if ((svi = malloc(sizeof (ndr_svinfo_t))) == NULL) { + (void) mutex_unlock(&ndr_svlist.svl_mtx); + return (-1); + } + + if (srvsvc_net_server_getinfo(server, domain, &svi->svi_svinfo) < 0) { + (void) mutex_unlock(&ndr_svlist.svl_mtx); + free(svi); + return (-1); + } + + (void) time(&svi->svi_tcached); + (void) strlcpy(svi->svi_server, server, MAXNAMELEN); + (void) strlcpy(svi->svi_domain, domain, MAXNAMELEN); + list_insert_tail(&ndr_svlist.svl_list, svi); + bcopy(&svi->svi_svinfo, svinfo, sizeof (srvsvc_server_info_t)); + (void) mutex_unlock(&ndr_svlist.svl_mtx); + return (0); +} + +static boolean_t +ndr_svinfo_match(const char *server, const char *domain, + const ndr_svinfo_t *svi) +{ + if ((utf8_strcasecmp(server, svi->svi_server) == 0) && + (utf8_strcasecmp(domain, svi->svi_domain) == 0)) { + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * If the server info in the cache has expired, discard it and return true. + * Otherwise return false. + * + * This is a private function to support ndr_svinfo_lookup() that assumes + * the list mutex is held. + */ +static boolean_t +ndr_svinfo_expired(ndr_svinfo_t *svi) +{ + time_t tnow; + + (void) time(&tnow); + + if (difftime(tnow, svi->svi_tcached) > NDR_SVINFO_TIMEOUT) { + list_remove(&ndr_svlist.svl_list, svi); + free(svi->svi_svinfo.sv_name); + free(svi->svi_svinfo.sv_comment); + free(svi); + return (B_TRUE); + } + + return (B_FALSE); +} diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c Mon Oct 05 11:03:34 2009 -0700 @@ -38,7 +38,6 @@ #include #include -#include #include #include @@ -49,7 +48,7 @@ /* * DC Locator */ -#define SMB_DCLOCATOR_TIMEOUT 45 +#define SMB_DCLOCATOR_TIMEOUT 45 /* seconds */ #define SMB_IS_FQDN(domain) (strchr(domain, '.') != NULL) typedef struct smb_dclocator { @@ -64,15 +63,15 @@ static smb_dclocator_t smb_dclocator; static pthread_t smb_dclocator_thr; -static void *smb_dclocator_main(void *); -static void smb_domain_update(char *, char *); -static boolean_t smb_domain_query_dns(char *, char *, smb_domain_t *); -static boolean_t smb_domain_query_nbt(char *, char *, smb_domain_t *); -static boolean_t smb_domain_match(char *, char *, uint32_t); -static uint32_t smb_domain_query(char *, char *, smb_domain_t *); -static void smb_domain_enum_trusted(char *, char *, smb_trusted_domains_t *); -static uint32_t smb_domain_use_config(char *, nt_domain_t *); -static void smb_domain_free(smb_domain_t *di); +static void *smb_ddiscover_service(void *); +static void smb_ddiscover_main(char *, char *); +static boolean_t smb_ddiscover_dns(char *, char *, smb_domainex_t *); +static boolean_t smb_ddiscover_nbt(char *, char *, smb_domainex_t *); +static boolean_t smb_ddiscover_domain_match(char *, char *, uint32_t); +static uint32_t smb_ddiscover_qinfo(char *, char *, smb_domainex_t *); +static void smb_ddiscover_enum_trusted(char *, char *, smb_domainex_t *); +static uint32_t smb_ddiscover_use_config(char *, smb_domainex_t *); +static void smb_domainex_free(smb_domainex_t *); /* * =================================================================== @@ -82,8 +81,6 @@ */ /* - * smb_dclocator_init - * * Initialization of the DC locator thread. * Returns 0 on success, an error number if thread creation fails. */ @@ -96,14 +93,12 @@ (void) pthread_attr_init(&tattr); (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); rc = pthread_create(&smb_dclocator_thr, &tattr, - smb_dclocator_main, 0); + smb_ddiscover_service, 0); (void) pthread_attr_destroy(&tattr); return (rc); } /* - * smb_locate_dc - * * This is the entry point for discovering a domain controller for the * specified domain. * @@ -121,11 +116,11 @@ * Returns B_TRUE if the DC/domain info is available. */ boolean_t -smb_locate_dc(char *domain, char *dc, smb_domain_t *dp) +smb_locate_dc(char *domain, char *dc, smb_domainex_t *dp) { int rc; timestruc_t to; - smb_domain_t domain_info; + smb_domainex_t domain_info; if (domain == NULL || *domain == '\0') return (B_FALSE); @@ -160,31 +155,21 @@ } /* - * Returns a copy of primary domain information plus - * the selected domain controller - */ -boolean_t -smb_domain_getinfo(smb_domain_t *dp) -{ - return (nt_domain_get_primary(dp)); -} - -/* * ========================================================== * DC discovery functions * ========================================================== */ /* - * This is the DC discovery thread: it gets woken up whenever someone - * wants to locate a domain controller. + * This is the domain and DC discovery service: it gets woken up whenever + * there is need to locate a domain controller. * * Upon success, the SMB domain cache will be populated with the discovered * DC and domain info. */ /*ARGSUSED*/ static void * -smb_dclocator_main(void *arg) +smb_ddiscover_service(void *arg) { char domain[SMB_PI_MAX_DOMAIN]; char sought_dc[MAXHOSTNAMELEN]; @@ -201,7 +186,7 @@ (void) strlcpy(sought_dc, smb_dclocator.sdl_dc, MAXHOSTNAMELEN); (void) mutex_unlock(&smb_dclocator.sdl_mtx); - smb_domain_update(domain, sought_dc); + smb_ddiscover_main(domain, sought_dc); (void) mutex_lock(&smb_dclocator.sdl_mtx); smb_dclocator.sdl_locate = B_FALSE; @@ -223,29 +208,30 @@ * obtained information. */ static void -smb_domain_update(char *domain, char *server) +smb_ddiscover_main(char *domain, char *server) { - smb_domain_t di; - boolean_t query_ok; + smb_domainex_t dxi; + boolean_t discovered; - bzero(&di, sizeof (smb_domain_t)); + bzero(&dxi, sizeof (smb_domainex_t)); - nt_domain_start_update(); + if (smb_domain_start_update() != SMB_DOMAIN_SUCCESS) + return; if (SMB_IS_FQDN(domain)) - query_ok = smb_domain_query_dns(domain, server, &di); + discovered = smb_ddiscover_dns(domain, server, &dxi); else - query_ok = smb_domain_query_nbt(domain, server, &di); + discovered = smb_ddiscover_nbt(domain, server, &dxi); - if (query_ok) - nt_domain_update(&di); + if (discovered) + smb_domain_update(&dxi); - nt_domain_end_update(); + smb_domain_end_update(); - smb_domain_free(&di); + smb_domainex_free(&dxi); - if (query_ok) - nt_domain_save(); + if (discovered) + smb_domain_save(); } /* @@ -253,13 +239,14 @@ * primary and trusted domains information will be queried. */ static boolean_t -smb_domain_query_dns(char *domain, char *server, smb_domain_t *di) +smb_ddiscover_dns(char *domain, char *server, smb_domainex_t *dxi) { uint32_t status; - if (!smb_ads_lookup_msdcs(domain, server, di->d_dc, MAXHOSTNAMELEN)) + + if (!smb_ads_lookup_msdcs(domain, server, dxi->d_dc, MAXHOSTNAMELEN)) return (B_FALSE); - status = smb_domain_query(domain, di->d_dc, di); + status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi); return (status == NT_STATUS_SUCCESS); } @@ -277,30 +264,30 @@ * actually for another domain, whose first label of its FQDN somehow * matches with the NetBIOS name of the domain we're interested in. */ - static boolean_t -smb_domain_query_nbt(char *domain, char *server, smb_domain_t *di) +smb_ddiscover_nbt(char *domain, char *server, smb_domainex_t *dxi) { char dnsdomain[MAXHOSTNAMELEN]; uint32_t status; *dnsdomain = '\0'; - if (!smb_browser_netlogon(domain, di->d_dc, MAXHOSTNAMELEN)) { - if (!smb_domain_match(domain, dnsdomain, MAXHOSTNAMELEN)) + if (!smb_browser_netlogon(domain, dxi->d_dc, MAXHOSTNAMELEN)) { + if (!smb_ddiscover_domain_match(domain, dnsdomain, + MAXHOSTNAMELEN)) return (B_FALSE); - if (!smb_ads_lookup_msdcs(dnsdomain, server, di->d_dc, + if (!smb_ads_lookup_msdcs(dnsdomain, server, dxi->d_dc, MAXHOSTNAMELEN)) return (B_FALSE); } - status = smb_domain_query(domain, di->d_dc, di); + status = smb_ddiscover_qinfo(domain, dxi->d_dc, dxi); if (status != NT_STATUS_SUCCESS) return (B_FALSE); if ((*dnsdomain != '\0') && - utf8_strcasecmp(domain, di->d_info.di_nbname)) + utf8_strcasecmp(domain, dxi->d_primary.di_nbname)) return (B_FALSE); /* @@ -309,8 +296,8 @@ * if we previously locate a DC via NetBIOS. On success, * ADS cache will be populated. */ - if (smb_ads_lookup_msdcs(di->d_info.di_fqname, server, - di->d_dc, MAXHOSTNAMELEN) == 0) + if (smb_ads_lookup_msdcs(dxi->d_primary.di_fqname, server, + dxi->d_dc, MAXHOSTNAMELEN) == 0) return (B_FALSE); return (B_TRUE); @@ -322,7 +309,7 @@ * If a match is found, it'll be returned in the passed buffer. */ static boolean_t -smb_domain_match(char *nb_domain, char *buf, uint32_t len) +smb_ddiscover_domain_match(char *nb_domain, char *buf, uint32_t len) { struct __res_state res_state; int i; @@ -373,22 +360,22 @@ * domain - either NetBIOS or fully-qualified domain name */ static uint32_t -smb_domain_query(char *domain, char *server, smb_domain_t *di) +smb_ddiscover_qinfo(char *domain, char *server, smb_domainex_t *dxi) { uint32_t status; mlsvc_disconnect(server); - status = lsa_query_dns_domain_info(server, domain, &di->d_info); + status = lsa_query_dns_domain_info(server, domain, &dxi->d_primary); if (status != NT_STATUS_SUCCESS) { - status = smb_domain_use_config(domain, &di->d_info); + status = smb_ddiscover_use_config(domain, dxi); if (status != NT_STATUS_SUCCESS) status = lsa_query_primary_domain_info(server, domain, - &di->d_info); + &dxi->d_primary); } if (status == NT_STATUS_SUCCESS) - smb_domain_enum_trusted(domain, server, &di->d_trusted); + smb_ddiscover_enum_trusted(domain, server, dxi); return (status); } @@ -399,10 +386,12 @@ * domain - either NetBIOS or fully-qualified domain name. */ static void -smb_domain_enum_trusted(char *domain, char *server, smb_trusted_domains_t *list) +smb_ddiscover_enum_trusted(char *domain, char *server, smb_domainex_t *dxi) { + smb_trusted_domains_t *list; uint32_t status; + list = &dxi->d_trusted; status = lsa_enum_trusted_domains_ex(server, domain, list); if (status != NT_STATUS_SUCCESS) (void) lsa_enum_trusted_domains(server, domain, list); @@ -410,15 +399,17 @@ /* * If the domain to be discovered matches the current domain (i.e the - * value of either domain or fqdn configuration), the output parameter - * 'dinfo' will be set to the information stored in SMF. + * value of either domain or fqdn configuration), then get the primary + * domain information from SMF. */ static uint32_t -smb_domain_use_config(char *domain, nt_domain_t *dinfo) +smb_ddiscover_use_config(char *domain, smb_domainex_t *dxi) { boolean_t use; + smb_domain_t *dinfo; - bzero(dinfo, sizeof (nt_domain_t)); + dinfo = &dxi->d_primary; + bzero(dinfo, sizeof (smb_domain_t)); if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) return (NT_STATUS_UNSUCCESSFUL); @@ -440,7 +431,7 @@ } static void -smb_domain_free(smb_domain_t *di) +smb_domainex_free(smb_domainex_t *dxi) { - free(di->d_trusted.td_domains); + free(dxi->d_trusted.td_domains); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c Mon Oct 05 11:03:34 2009 -0700 @@ -60,6 +60,7 @@ if ((rc = smb_dclocator_init()) != 0) return (rc); + ndr_rpc_init(); srvsvc_initialize(); wkssvc_initialize(); lsarpc_initialize(); @@ -86,6 +87,7 @@ smb_logon_fini(); svcctl_finalize(); logr_finalize(); + ndr_rpc_fini(); } /*ARGSUSED*/ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c Mon Oct 05 11:03:34 2009 -0700 @@ -520,7 +520,7 @@ struct mslsa_GetConnectedUser *param = arg; smb_netuserinfo_t *user = &mxa->pipe->np_user; DWORD status = NT_STATUS_SUCCESS; - smb_domain_t di; + smb_domainex_t di; int rc1; int rc2; @@ -638,16 +638,16 @@ lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *info, ndr_xa_t *mxa) { - nt_domain_t di; + smb_domain_t di; boolean_t found; int rc; bzero(info, sizeof (struct mslsa_PrimaryDomainInfo)); if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) - found = nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di); + found = smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di); else - found = nt_domain_lookup_type(NT_DOMAIN_PRIMARY, &di); + found = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &di); if (!found) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); @@ -676,12 +676,12 @@ lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *info, ndr_xa_t *mxa) { - nt_domain_t di; + smb_domain_t di; int rc; bzero(info, sizeof (struct mslsa_AccountDomainInfo)); - if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di)) + if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); rc = NDR_MSTRING(mxa, di.di_nbname, (ndr_mstring_t *)&info->name); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c Mon Oct 05 11:03:34 2009 -0700 @@ -59,7 +59,7 @@ typedef struct samr_keydata { samr_key_t kd_key; - nt_domain_type_t kd_type; + smb_domain_type_t kd_type; DWORD kd_rid; } samr_keydata_t; @@ -93,7 +93,7 @@ #define SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser) -static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, nt_domain_type_t, +static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t, DWORD); static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *); static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t); @@ -147,7 +147,7 @@ * Handle allocation wrapper to setup the local context. */ static ndr_hdid_t * -samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, nt_domain_type_t domain_type, +samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type, DWORD rid) { samr_keydata_t *data; @@ -213,7 +213,7 @@ struct samr_ConnectAnon *param = arg; ndr_hdid_t *id; - id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); if (id) { bcopy(id, ¶m->handle, sizeof (samr_handle_t)); param->status = 0; @@ -257,7 +257,7 @@ { struct samr_LookupDomain *param = arg; char *domain_name; - nt_domain_t di; + smb_domain_t di; if ((domain_name = (char *)param->domain_name.str) == NULL) { bzero(param, sizeof (struct samr_LookupDomain)); @@ -265,7 +265,7 @@ return (NDR_DRC_OK); } - if (!nt_domain_lookup_name(domain_name, &di)) { + if (!smb_domain_lookup_name(domain_name, &di)) { bzero(param, sizeof (struct samr_LookupDomain)); param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN); return (NDR_DRC_OK); @@ -370,7 +370,7 @@ { struct samr_OpenDomain *param = arg; ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - nt_domain_t domain; + smb_domain_t domain; if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); @@ -378,14 +378,14 @@ return (NDR_DRC_OK); } - if (!nt_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) { + if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); return (NDR_DRC_OK); } - if ((domain.di_type != NT_DOMAIN_BUILTIN) && - (domain.di_type != NT_DOMAIN_LOCAL)) { + if ((domain.di_type != SMB_DOMAIN_BUILTIN) && + (domain.di_type != SMB_DOMAIN_LOCAL)) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); return (NDR_DRC_OK); @@ -444,13 +444,13 @@ data = (samr_keydata_t *)hd->nh_data; switch (data->kd_type) { - case NT_DOMAIN_BUILTIN: + case SMB_DOMAIN_BUILTIN: domain = "BUILTIN"; user_cnt = 0; alias_cnt = smb_sam_grp_cnt(data->kd_type); break; - case NT_DOMAIN_LOCAL: + case SMB_DOMAIN_LOCAL: rc = smb_getnetbiosname(hostname, sizeof (hostname)); if (rc == 0) { domain = hostname; @@ -560,7 +560,7 @@ data = (samr_keydata_t *)hd->nh_data; switch (data->kd_type) { - case NT_DOMAIN_BUILTIN: + case SMB_DOMAIN_BUILTIN: wka = smb_wka_lookup_name((char *)param->name.str); if (wka != NULL) { param->rids.n_entry = 1; @@ -573,7 +573,7 @@ } break; - case NT_DOMAIN_LOCAL: + case SMB_DOMAIN_LOCAL: status = smb_sam_lookup_name(NULL, (char *)param->name.str, SidTypeUnknown, &account); if (status == NT_STATUS_SUCCESS) { @@ -697,7 +697,7 @@ smb_sid_t *user_sid = NULL; smb_group_t grp; smb_giter_t gi; - nt_domain_t di; + smb_domain_t di; uint32_t status; int size; int ngrp_max; @@ -709,9 +709,9 @@ data = (samr_keydata_t *)hd->nh_data; switch (data->kd_type) { - case NT_DOMAIN_BUILTIN: - case NT_DOMAIN_LOCAL: - if (!nt_domain_lookup_type(data->kd_type, &di)) { + case SMB_DOMAIN_BUILTIN: + case SMB_DOMAIN_LOCAL: + if (!smb_domain_lookup_type(data->kd_type, &di)) { status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto query_error; } @@ -828,7 +828,7 @@ struct samr_Connect *param = arg; ndr_hdid_t *id; - id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0); if (id) { bcopy(id, ¶m->handle, sizeof (samr_handle_t)); param->status = 0; @@ -956,10 +956,10 @@ data = (samr_keydata_t *)hd->nh_data; switch (data->kd_type) { - case NT_DOMAIN_BUILTIN: + case SMB_DOMAIN_BUILTIN: goto no_info; - case NT_DOMAIN_LOCAL: + case SMB_DOMAIN_LOCAL: num_users = smb_sam_usr_cnt(); start_idx = param->start_idx; if ((num_users == 0) || (start_idx >= num_users)) diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c Mon Oct 05 11:03:34 2009 -0700 @@ -38,9 +38,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -138,21 +138,21 @@ * Returns NT status codes. */ DWORD -mlsvc_join(smb_domain_t *dinfo, char *user, char *plain_text) +mlsvc_join(smb_domainex_t *dxi, char *user, char *plain_text) { int erc; DWORD status; char machine_passwd[NETR_MACHINE_ACCT_PASSWD_MAX]; smb_adjoin_status_t err; - nt_domain_t *domain; + smb_domain_t *domain; machine_passwd[0] = '\0'; - domain = &dinfo->d_info; + domain = &dxi->d_primary; - mlsvc_disconnect(dinfo->d_dc); + mlsvc_disconnect(dxi->d_dc); - erc = mlsvc_logon(dinfo->d_dc, domain->di_nbname, user); + erc = smbrdr_logon(dxi->d_dc, domain->di_nbname, user); if (erc == AUTH_USER_GRANT) { if (mlsvc_ntjoin_support == B_FALSE) { @@ -167,7 +167,7 @@ } } else { - status = sam_create_trust_account(dinfo->d_dc, + status = sam_create_trust_account(dxi->d_dc, domain->di_nbname); if (status == NT_STATUS_SUCCESS) { (void) smb_getnetbiosname(machine_passwd, @@ -177,7 +177,7 @@ } if (status == NT_STATUS_SUCCESS) { - erc = smb_setdomainprops(NULL, dinfo->d_dc, + erc = smb_setdomainprops(NULL, dxi->d_dc, machine_passwd); if (erc != 0) { syslog(LOG_NOTICE, "Failed to update CIFS " @@ -185,7 +185,7 @@ return (NT_STATUS_UNSUCCESSFUL); } - status = mlsvc_netlogon(dinfo->d_dc, domain->di_nbname); + status = mlsvc_netlogon(dxi->d_dc, domain->di_nbname); } } else { status = NT_STATUS_LOGON_FAILURE; @@ -193,3 +193,15 @@ return (status); } + +int +mlsvc_ping(const char *server) +{ + return (smbrdr_echo(server)); +} + +void +mlsvc_disconnect(const char *server) +{ + smbrdr_disconnect(server); +} diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c Mon Oct 05 11:03:34 2009 -0700 @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -127,18 +126,13 @@ int netr_open(char *server, char *domain, mlsvc_handle_t *netr_handle) { - srvsvc_server_info_t svinfo; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; - if (srvsvc_net_server_getinfo(server, domain, &svinfo) < 0) - return (-1); + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (ndr_rpc_bind(netr_handle, server, domain, user, "NETR") < 0) return (-1); - ndr_rpc_server_setinfo(netr_handle, &svinfo); - free(svinfo.sv_name); - free(svinfo.sv_comment); return (0); } @@ -214,7 +208,7 @@ arg.hostname = (unsigned char *)netr_info->hostname; arg.negotiate_flags = NETR_NEGOTIATE_BASE_FLAGS; - if (ndr_rpc_server_os(netr_handle) != NATIVE_OS_WINNT) { + if (ndr_rpc_server_os(netr_handle) == NATIVE_OS_WIN2000) { arg.negotiate_flags |= NETR_NEGOTIATE_STRONGKEY_FLAG; if (netr_gen_skey128(netr_info) != SMBAUTH_SUCCESS) return (-1); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c Mon Oct 05 11:03:34 2009 -0700 @@ -37,7 +37,6 @@ #include #include -#include #include #include #include @@ -104,7 +103,7 @@ char resource_domain[SMB_PI_MAX_DOMAIN]; char server[NETBIOS_NAME_SZ * 2]; mlsvc_handle_t netr_handle; - smb_domain_t di; + smb_domainex_t di; uint32_t status; int retries = 0, server_changed = 0; @@ -113,7 +112,7 @@ if (!smb_domain_getinfo(&di)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - if ((mlsvc_echo(di.d_dc)) < 0) { + if (mlsvc_ping(di.d_dc) < 0) { /* * We had a session to the DC but it's not responding. * So drop the credential chain. @@ -123,7 +122,8 @@ } do { - if (netr_open(di.d_dc, di.d_info.di_nbname, &netr_handle) != 0) + if (netr_open(di.d_dc, di.d_primary.di_nbname, &netr_handle) + != 0) return (NT_STATUS_OPEN_FAILED); if (di.d_dc && (*netr_global_info.server != '\0')) { @@ -677,13 +677,13 @@ static boolean_t netr_isadmin(struct netr_validation_info3 *info3) { - nt_domain_t di; + smb_domain_t di; int i; - if (!nt_domain_lookup_sid((smb_sid_t *)info3->LogonDomainId, &di)) + if (!smb_domain_lookup_sid((smb_sid_t *)info3->LogonDomainId, &di)) return (B_FALSE); - if (di.di_type != NT_DOMAIN_PRIMARY) + if (di.di_type != SMB_DOMAIN_PRIMARY) return (B_FALSE); if ((info3->UserId == DOMAIN_USER_RID_ADMIN) || diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/samlib.c --- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c Mon Oct 05 11:03:34 2009 -0700 @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -114,7 +113,9 @@ DWORD rid; DWORD status; int rc; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT, &samr_handle); @@ -199,7 +200,9 @@ DWORD access_mask; DWORD status; int rc; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION, &samr_handle); @@ -250,7 +253,9 @@ DWORD access_mask; DWORD status; int rc; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION, &samr_handle); @@ -306,7 +311,9 @@ struct samr_sid *domain_sid; int rc; DWORD status; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); *rid_ret = 0; @@ -352,7 +359,9 @@ mlsvc_handle_t samr_handle; DWORD status; int rc; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = samr_open(server, domain_name, user, SAM_ENUM_LOCAL_DOMAIN, &samr_handle); @@ -399,21 +408,20 @@ static struct samr_sid * sam_get_domain_sid(mlsvc_handle_t *samr_handle, char *server, char *domain_name) { - struct samr_sid *sid = NULL; - smb_domain_t domain; + smb_sid_t *sid = NULL; + smb_domainex_t domain; if (ndr_rpc_server_os(samr_handle) == NATIVE_OS_WIN2000) { if (!smb_domain_getinfo(&domain)) { if (lsa_query_account_domain_info(server, domain_name, - &domain.d_info) != NT_STATUS_SUCCESS) + &domain.d_primary) != NT_STATUS_SUCCESS) return (NULL); } - sid = (struct samr_sid *)smb_sid_fromstr(domain.d_info.di_sid); + sid = smb_sid_fromstr(domain.d_primary.di_sid); } else { - sid = (struct samr_sid *)samr_lookup_domain(samr_handle, - domain_name); + sid = samr_lookup_domain(samr_handle, domain_name); } - return (sid); + return ((struct samr_sid *)sid); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/samr_open.c --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c Mon Oct 05 11:03:34 2009 -0700 @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -55,6 +54,9 @@ static DWORD samr_connect3(char *, char *, char *, DWORD, mlsvc_handle_t *); static DWORD samr_connect4(char *, char *, char *, DWORD, mlsvc_handle_t *); +typedef DWORD (*samr_connop_t)(char *, char *, char *, DWORD, + mlsvc_handle_t *); + /* * samr_open * @@ -71,7 +73,7 @@ samr_open(char *server, char *domain, char *username, DWORD access_mask, mlsvc_handle_t *samr_handle) { - smb_domain_t di; + smb_domainex_t di; int rc; if (server == NULL || domain == NULL) { @@ -79,7 +81,7 @@ return (-1); server = di.d_dc; - domain = di.d_info.di_nbname; + domain = di.d_primary.di_nbname; } if (username == NULL) @@ -93,38 +95,41 @@ /* * samr_connect * - * Connect to the SAM on the specified server (domain controller). - * This is the entry point for the various SAM connect calls. We do - * parameter validation and open the samr named pipe here. The actual - * RPC is based on the native OS of the server. + * Connect to the SAMR service on the specified server (domain controller). + * New SAM connect calls have been added to Windows over time: * - * Returns 0 on success. Otherwise returns a -ve error code. + * Windows NT3.x: SamrConnect + * Windows NT4.0: SamrConnect2 + * Windows 2000: SamrConnect3 + * Windows XP: SamrConnect4 + * + * Try the calls from most recent to oldest until the server responds with + * something other than an RPC protocol error. We don't use the original + * connect call because all supported servers should support SamrConnect2. */ int samr_connect(char *server, char *domain, char *username, DWORD access_mask, mlsvc_handle_t *samr_handle) { - DWORD status; + static samr_connop_t samr_connop[] = { + samr_connect4, + samr_connect3, + samr_connect2 + }; + + int n_op = (sizeof (samr_connop) / sizeof (samr_connop[0])); + DWORD status; + int i; if (ndr_rpc_bind(samr_handle, server, domain, username, "SAMR") < 0) return (-1); - switch (ndr_rpc_server_os(samr_handle)) { - case NATIVE_OS_NT5_1: - status = samr_connect4(server, domain, username, access_mask, - samr_handle); - break; + for (i = 0; i < n_op; ++i) { + status = (*samr_connop[i])(server, domain, username, + access_mask, samr_handle); - case NATIVE_OS_NT5_0: - status = samr_connect3(server, domain, username, access_mask, - samr_handle); - break; - - case NATIVE_OS_NT4_0: - default: - status = samr_connect2(server, domain, username, access_mask, - samr_handle); - break; + if (status != NT_STATUS_UNSUCCESSFUL) + break; } if (status != NT_STATUS_SUCCESS) { @@ -244,7 +249,7 @@ len = strlen(server) + 4; arg.servername = ndr_rpc_malloc(samr_handle, len); (void) snprintf((char *)arg.servername, len, "\\\\%s", server); - arg.unknown_02 = 0x00000002; + arg.revision = SAMR_REVISION_2; arg.access_mask = access_mask; if (ndr_rpc_call(samr_handle, opnum, &arg) != 0) { @@ -283,7 +288,7 @@ int len; int opnum; DWORD status; - smb_domain_t dinfo; + smb_domainex_t dinfo; bzero(&arg, sizeof (struct samr_Connect4)); opnum = SAMR_OPNUM_Connect; @@ -292,12 +297,12 @@ if (!smb_domain_getinfo(&dinfo)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - len = strlen(server) + strlen(dinfo.d_info.di_fqname) + 4; + len = strlen(server) + strlen(dinfo.d_primary.di_fqname) + 4; arg.servername = ndr_rpc_malloc(samr_handle, len); - if (*dinfo.d_info.di_fqname != '\0') + if (*dinfo.d_primary.di_fqname != '\0') (void) snprintf((char *)arg.servername, len, "\\\\%s.%s", - server, dinfo.d_info.di_fqname); + server, dinfo.d_primary.di_fqname); else (void) snprintf((char *)arg.servername, len, "\\\\%s", server); @@ -572,7 +577,7 @@ ndr_heap_mkvcs(heap, username, (ndr_vcstr_t *)&arg.username); arg.account_flags = account_flags; - arg.unknown_e00500b0 = 0xE00500B0; + arg.desired_access = 0xE00500B0; rc = ndr_rpc_call(domain_handle, opnum, &arg); if (rc != 0) { diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Mon Oct 05 11:03:34 2009 -0700 @@ -490,13 +490,13 @@ char guest[SMB_USERNAME_MAXLEN]; smb_passwd_t smbpw; uint32_t status; - nt_domain_t domain; + smb_domain_t domain; boolean_t isguest; /* Make sure this is not a domain user */ if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { - if (nt_domain_lookup_name(clnt->e_domain, &domain)) { - if (domain.di_type != NT_DOMAIN_LOCAL) + if (smb_domain_lookup_name(clnt->e_domain, &domain)) { + if (domain.di_type != SMB_DOMAIN_LOCAL) return (NT_STATUS_INVALID_LOGON_TYPE); } } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c --- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_clnt.c Mon Oct 05 11:03:34 2009 -0700 @@ -39,7 +39,6 @@ #include #include -#include #include #include #include @@ -61,14 +60,14 @@ static int srvsvc_open(char *server, char *domain, char *username, mlsvc_handle_t *handle) { - smb_domain_t di; + smb_domainex_t di; if (server == NULL || domain == NULL) { if (!smb_domain_getinfo(&di)) return (-1); server = di.d_dc; - domain = di.d_info.di_nbname; + domain = di.d_primary.di_nbname; } if (username == NULL) @@ -105,13 +104,13 @@ struct mslm_NetShareInfo_1 *info1; struct mslm_NetShareInfo_2 *info2; int len; - char *user = NULL; + char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); if (srvsvc_info_level == 2) - user = smbrdr_ipc_get_user(); + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (srvsvc_open(server, domain, user, &handle) != 0) return (-1); @@ -195,11 +194,13 @@ struct mslm_infonres infonres; struct mslm_SESSION_INFO_1 *nsi1; int len; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); + rc = srvsvc_open(server, domain, user, &handle); if (rc != 0) return (-1); @@ -260,11 +261,13 @@ struct mslm_NetConnectInfo0 info0; struct mslm_NetConnectInfoBuf1 *cib1; int len; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; if (netname == NULL) return (-1); + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); + rc = srvsvc_open(server, domain, user, &handle); if (rc != 0) return (-1); @@ -347,6 +350,10 @@ return (0); } +/* + * Windows 95+ and Windows NT4.0 both report the version as 4.0. + * Windows 2000+ reports the version as 5.x. + */ int srvsvc_net_server_getinfo(char *server, char *domain, srvsvc_server_info_t *svinfo) @@ -355,7 +362,9 @@ struct mslm_NetServerGetInfo arg; struct mslm_SERVER_INFO_101 *sv101; int len, opnum, rc; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); if (srvsvc_open(server, domain, user, &handle) != 0) return (-1); @@ -389,6 +398,16 @@ if (sv101->sv101_comment) svinfo->sv_comment = strdup((char *)sv101->sv101_comment); + if (svinfo->sv_type & SV_TYPE_WFW) + svinfo->sv_os = NATIVE_OS_WIN95; + if (svinfo->sv_type & SV_TYPE_WINDOWS) + svinfo->sv_os = NATIVE_OS_WIN95; + if ((svinfo->sv_type & SV_TYPE_NT) || + (svinfo->sv_type & SV_TYPE_SERVER_NT)) + svinfo->sv_os = NATIVE_OS_WINNT; + if (svinfo->sv_version_major > 4) + svinfo->sv_os = NATIVE_OS_WIN2000; + srvsvc_close(&handle); return (0); } @@ -399,7 +418,7 @@ void srvsvc_timesync(void) { - smb_domain_t di; + smb_domainex_t di; struct timeval tv; struct tm tm; time_t tsecs; @@ -407,7 +426,8 @@ if (!smb_domain_getinfo(&di)) return; - if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &tv, &tm) != 0) + if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) + != 0) return; if (settimeofday(&tv, 0)) @@ -424,14 +444,15 @@ int srvsvc_gettime(unsigned long *t) { - smb_domain_t di; + smb_domainex_t di; struct timeval tv; struct tm tm; if (!smb_domain_getinfo(&di)) return (-1); - if (srvsvc_net_remote_tod(di.d_dc, di.d_info.di_nbname, &tv, &tm) != 0) + if (srvsvc_net_remote_tod(di.d_dc, di.d_primary.di_nbname, &tv, &tm) + != 0) return (-1); *t = tv.tv_sec; @@ -477,7 +498,9 @@ int rc; int opnum; int len; - char *user = smbrdr_ipc_get_user(); + char user[SMB_USERNAME_MAXLEN]; + + smb_ipc_get_user(user, SMB_USERNAME_MAXLEN); rc = srvsvc_open(server, domain, user, &handle); if (rc != 0) @@ -535,14 +558,14 @@ void srvsvc_net_test(char *server, char *domain, char *netname) { - smb_domain_t di; + smb_domainex_t di; srvsvc_server_info_t svinfo; (void) smb_tracef("%s %s %s", server, domain, netname); if (smb_domain_getinfo(&di)) { server = di.d_dc; - domain = di.d_info.di_nbname; + domain = di.d_primary.di_nbname; } if (srvsvc_net_server_getinfo(server, domain, &svinfo) == 0) { diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmb/common/libsmb.h --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h Mon Oct 05 11:03:34 2009 -0700 @@ -484,6 +484,16 @@ unsigned char *, int, char *, char *, uchar_t *); /* + * SMB authenticated IPC + */ +extern void smb_ipc_commit(void); +extern void smb_ipc_get_user(char *, size_t); +extern void smb_ipc_get_passwd(uint8_t *, size_t); +extern void smb_ipc_init(void); +extern void smb_ipc_rollback(void); +extern void smb_ipc_set(char *, uint8_t *); + +/* * SMB MAC Signing */ @@ -553,16 +563,16 @@ * that the system joined. All other domains are either * trusted or untrusted, as defined by the primary domain PDC. */ -typedef enum nt_domain_type { - NT_DOMAIN_NULL, - NT_DOMAIN_BUILTIN, - NT_DOMAIN_LOCAL, - NT_DOMAIN_PRIMARY, - NT_DOMAIN_ACCOUNT, - NT_DOMAIN_TRUSTED, - NT_DOMAIN_UNTRUSTED, - NT_DOMAIN_NUM_TYPES -} nt_domain_type_t; +typedef enum smb_domain_type { + SMB_DOMAIN_NULL, + SMB_DOMAIN_BUILTIN, + SMB_DOMAIN_LOCAL, + SMB_DOMAIN_PRIMARY, + SMB_DOMAIN_ACCOUNT, + SMB_DOMAIN_TRUSTED, + SMB_DOMAIN_UNTRUSTED, + SMB_DOMAIN_NUM_TYPES +} smb_domain_type_t; /* * Information specific to trusted domains @@ -586,9 +596,9 @@ /* * This is the information that is held about each domain. */ -typedef struct nt_domain { +typedef struct smb_domain { list_node_t di_lnd; - nt_domain_type_t di_type; + smb_domain_type_t di_type; char di_sid[SMB_SID_STRSZ]; char di_nbname[NETBIOS_NAME_SZ]; char di_fqname[MAXHOSTNAMELEN]; @@ -597,11 +607,11 @@ smb_domain_dns_t di_dns; smb_domain_trust_t di_trust; } di_u; -} nt_domain_t; +} smb_domain_t; typedef struct smb_trusted_domains { uint32_t td_num; - nt_domain_t *td_domains; + smb_domain_t *td_domains; } smb_trusted_domains_t; #define SMB_DOMAIN_SUCCESS 0 @@ -611,29 +621,38 @@ #define SMB_DOMAIN_INTERNAL_ERR 4 #define SMB_DOMAIN_INVALID_ARG 5 #define SMB_DOMAIN_NO_MEMORY 6 +#define SMB_DOMAIN_NO_CACHE 7 -typedef struct smb_domain { +/* + * This structure could contain information about + * the primary domain the name of selected domain controller + * for the primary domain and a list of trusted domains if + * any. The "ex" in the structure name stands for extended. + * This is to differentiate this structure from smb_domain_t + * which only contains information about a single domain. + */ +typedef struct smb_domainex { char d_dc[MAXHOSTNAMELEN]; - nt_domain_t d_info; + smb_domain_t d_primary; smb_trusted_domains_t d_trusted; -} smb_domain_t; +} smb_domainex_t; -int nt_domain_init(uint32_t); -void nt_domain_fini(void); -void nt_domain_show(void); -void nt_domain_save(void); -boolean_t nt_domain_lookup_name(char *, nt_domain_t *); -boolean_t nt_domain_lookup_sid(smb_sid_t *, nt_domain_t *); -boolean_t nt_domain_lookup_type(nt_domain_type_t, nt_domain_t *); -boolean_t nt_domain_get_primary(smb_domain_t *); -void nt_domain_update(smb_domain_t *); -void nt_domain_start_update(void); -void nt_domain_end_update(void); -void nt_domain_set_basic_info(char *, char *, char *, nt_domain_t *); -void nt_domain_set_dns_info(char *, char *, char *, char *, char *, - nt_domain_t *); -void nt_domain_set_trust_info(char *, char *, char *, - uint32_t, uint32_t, uint32_t, nt_domain_t *); +int smb_domain_init(uint32_t); +void smb_domain_fini(void); +void smb_domain_show(void); +void smb_domain_save(void); +boolean_t smb_domain_lookup_name(char *, smb_domain_t *); +boolean_t smb_domain_lookup_sid(smb_sid_t *, smb_domain_t *); +boolean_t smb_domain_lookup_type(smb_domain_type_t, smb_domain_t *); +boolean_t smb_domain_getinfo(smb_domainex_t *); +void smb_domain_update(smb_domainex_t *); +uint32_t smb_domain_start_update(void); +void smb_domain_end_update(void); +void smb_domain_set_basic_info(char *, char *, char *, smb_domain_t *); +void smb_domain_set_dns_info(char *, char *, char *, char *, char *, + smb_domain_t *); +void smb_domain_set_trust_info(char *, char *, char *, + uint32_t, uint32_t, uint32_t, smb_domain_t *); typedef enum { SMB_LGRP_BUILTIN = 1, @@ -823,7 +842,7 @@ uint32_t smb_sam_lookup_sid(smb_sid_t *, smb_account_t *); int smb_sam_usr_cnt(void); uint32_t smb_sam_usr_groups(smb_sid_t *, smb_ids_t *); -int smb_sam_grp_cnt(nt_domain_type_t); +int smb_sam_grp_cnt(smb_domain_type_t); void smb_account_free(smb_account_t *); boolean_t smb_account_validate(smb_account_t *); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmb/common/mapfile-vers --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Mon Oct 05 11:03:34 2009 -0700 @@ -84,20 +84,6 @@ mts_wctomb; netr_client_mkabsolute; netr_client_xfree; - nt_domain_end_update; - nt_domain_fini; - nt_domain_get_primary; - nt_domain_init; - nt_domain_lookup_name; - nt_domain_lookup_sid; - nt_domain_lookup_type; - nt_domain_save; - nt_domain_set_basic_info; - nt_domain_set_dns_info; - nt_domain_set_trust_info; - nt_domain_show; - nt_domain_start_update; - nt_domain_update; oem_get_smb_cpid; oem_get_telnet_cpid; oem_language_set; @@ -149,6 +135,20 @@ smb_ctxbuf_printf; smb_dlclose; smb_dlopen; + smb_domain_end_update; + smb_domain_fini; + smb_domain_getinfo; + smb_domain_init; + smb_domain_lookup_name; + smb_domain_lookup_sid; + smb_domain_lookup_type; + smb_domain_save; + smb_domain_set_basic_info; + smb_domain_set_dns_info; + smb_domain_set_trust_info; + smb_domain_show; + smb_domain_start_update; + smb_domain_update; smb_dr_clnt_call; smb_dr_clnt_cleanup; smb_dr_clnt_setup; @@ -220,6 +220,12 @@ smb_inet_equal; smb_inet_iszero; smb_inet_ntop; + smb_ipc_set; + smb_ipc_commit; + smb_ipc_init; + smb_ipc_rollback; + smb_ipc_get_user; + smb_ipc_get_passwd; smb_kmod_bind; smb_kmod_enum; smb_kmod_enum_init; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmb/common/smb_domain.c --- a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c Mon Oct 05 11:03:34 2009 -0700 @@ -77,21 +77,21 @@ static smb_domain_cache_t smb_dcache; -static uint32_t nt_domain_add(nt_domain_type_t, nt_domain_t *); -static uint32_t nt_domain_add_local(void); -static uint32_t nt_domain_add_primary(uint32_t); -static void nt_domain_unlink(void); +static uint32_t smb_domain_add(smb_domain_type_t, smb_domain_t *); +static uint32_t smb_domain_add_local(void); +static uint32_t smb_domain_add_primary(uint32_t); +static void smb_domain_unlink(void); static void smb_dcache_create(void); static void smb_dcache_destroy(void); static uint32_t smb_dcache_lock(int); static void smb_dcache_unlock(void); -static void smb_dcache_remove(nt_domain_t *); -static uint32_t smb_dcache_add(nt_domain_t *); +static void smb_dcache_remove(smb_domain_t *); +static uint32_t smb_dcache_add(smb_domain_t *); static void smb_dcache_getdc(char *, size_t); static void smb_dcache_setdc(char *); static boolean_t smb_dcache_wait(void); -static void smb_dcache_updating(void); +static uint32_t smb_dcache_updating(void); static void smb_dcache_ready(void); /* @@ -101,30 +101,30 @@ * Returns 0 on success and an error code on failure. */ int -nt_domain_init(uint32_t secmode) +smb_domain_init(uint32_t secmode) { - nt_domain_t di; + smb_domain_t di; int rc; smb_dcache_create(); - if ((rc = nt_domain_add_local()) != 0) + if ((rc = smb_domain_add_local()) != 0) return (rc); - nt_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di); - (void) nt_domain_add(NT_DOMAIN_BUILTIN, &di); + smb_domain_set_basic_info(NT_BUILTIN_DOMAIN_SIDSTR, "BUILTIN", "", &di); + (void) smb_domain_add(SMB_DOMAIN_BUILTIN, &di); - return (nt_domain_add_primary(secmode)); + return (smb_domain_add_primary(secmode)); } /* * Destroys the cache upon service termination */ void -nt_domain_fini(void) +smb_domain_fini(void) { smb_dcache_destroy(); - nt_domain_unlink(); + smb_domain_unlink(); } /* @@ -132,7 +132,7 @@ * for duplicates. */ static uint32_t -nt_domain_add(nt_domain_type_t type, nt_domain_t *di) +smb_domain_add(smb_domain_type_t type, smb_domain_t *di) { uint32_t res; @@ -160,13 +160,13 @@ * If the domain is not in the cache B_FALSE is returned. */ boolean_t -nt_domain_lookup_name(char *name, nt_domain_t *di) +smb_domain_lookup_name(char *name, smb_domain_t *di) { boolean_t found = B_FALSE; - nt_domain_t *dcnode; + smb_domain_t *dcnode; char *p; - bzero(di, sizeof (nt_domain_t)); + bzero(di, sizeof (smb_domain_t)); if (name == NULL || *name == '\0') return (B_FALSE); @@ -214,13 +214,13 @@ * If the domain is not in the cache B_FALSE is returned. */ boolean_t -nt_domain_lookup_sid(smb_sid_t *sid, nt_domain_t *di) +smb_domain_lookup_sid(smb_sid_t *sid, smb_domain_t *di) { boolean_t found = B_FALSE; - nt_domain_t *dcnode; + smb_domain_t *dcnode; char sidstr[SMB_SID_STRSZ]; - bzero(di, sizeof (nt_domain_t)); + bzero(di, sizeof (smb_domain_t)); if (sid == NULL) return (B_FALSE); @@ -257,12 +257,12 @@ * If the domain is not in the cache B_FALSE is returned. */ boolean_t -nt_domain_lookup_type(nt_domain_type_t type, nt_domain_t *di) +smb_domain_lookup_type(smb_domain_type_t type, smb_domain_t *di) { boolean_t found = B_FALSE; - nt_domain_t *dcnode; + smb_domain_t *dcnode; - bzero(di, sizeof (nt_domain_t)); + bzero(di, sizeof (smb_domain_t)); if (smb_dcache_lock(SMB_DCACHE_RDLOCK) != SMB_DOMAIN_SUCCESS) return (B_FALSE); @@ -288,13 +288,13 @@ * the selected domain controller. */ boolean_t -nt_domain_get_primary(smb_domain_t *domain) +smb_domain_getinfo(smb_domainex_t *dxi) { boolean_t success; - success = nt_domain_lookup_type(NT_DOMAIN_PRIMARY, &domain->d_info); + success = smb_domain_lookup_type(SMB_DOMAIN_PRIMARY, &dxi->d_primary); if (success) - smb_dcache_getdc(domain->d_dc, sizeof (domain->d_dc)); + smb_dcache_getdc(dxi->d_dc, sizeof (dxi->d_dc)); return (success); } @@ -304,17 +304,17 @@ * In this state any request for reading the cache would * be blocked until the update is finished. */ -void -nt_domain_start_update(void) +uint32_t +smb_domain_start_update(void) { - smb_dcache_updating(); + return (smb_dcache_updating()); } /* * Transfer the cache from updating to ready state. */ void -nt_domain_end_update(void) +smb_domain_end_update(void) { smb_dcache_ready(); } @@ -328,9 +328,9 @@ * primary and trusted will be removed from cache. */ void -nt_domain_update(smb_domain_t *domain) +smb_domain_update(smb_domainex_t *dxi) { - nt_domain_t *dcnode; + smb_domain_t *dcnode; int i; if (smb_dcache_lock(SMB_DCACHE_WRLOCK) != SMB_DOMAIN_SUCCESS) @@ -338,8 +338,8 @@ dcnode = list_head(&smb_dcache.dc_cache); while (dcnode) { - if ((dcnode->di_type == NT_DOMAIN_PRIMARY) || - (dcnode->di_type == NT_DOMAIN_TRUSTED)) { + if ((dcnode->di_type == SMB_DOMAIN_PRIMARY) || + (dcnode->di_type == SMB_DOMAIN_TRUSTED)) { smb_dcache_remove(dcnode); dcnode = list_head(&smb_dcache.dc_cache); } else { @@ -347,11 +347,11 @@ } } - if (smb_dcache_add(&domain->d_info) == SMB_DOMAIN_SUCCESS) { - for (i = 0; i < domain->d_trusted.td_num; i++) - (void) smb_dcache_add(&domain->d_trusted.td_domains[i]); + if (smb_dcache_add(&dxi->d_primary) == SMB_DOMAIN_SUCCESS) { + for (i = 0; i < dxi->d_trusted.td_num; i++) + (void) smb_dcache_add(&dxi->d_trusted.td_domains[i]); - smb_dcache_setdc(domain->d_dc); + smb_dcache_setdc(dxi->d_dc); } smb_dcache_unlock(); @@ -361,11 +361,11 @@ * Write the list of domains to /var/run/smb/domains. */ void -nt_domain_save(void) +smb_domain_save(void) { char fname[MAXPATHLEN]; char tag; - nt_domain_t *domain; + smb_domain_t *domain; FILE *fp; struct passwd *pwd; struct group *grp; @@ -393,16 +393,16 @@ domain = list_head(&smb_dcache.dc_cache); while (domain) { switch (domain->di_type) { - case NT_DOMAIN_PRIMARY: + case SMB_DOMAIN_PRIMARY: tag = '*'; break; - case NT_DOMAIN_TRUSTED: - case NT_DOMAIN_UNTRUSTED: + case SMB_DOMAIN_TRUSTED: + case SMB_DOMAIN_UNTRUSTED: tag = '-'; break; - case NT_DOMAIN_LOCAL: + case SMB_DOMAIN_LOCAL: tag = '.'; break; default: @@ -425,7 +425,7 @@ * List the domains in /var/run/smb/domains. */ void -nt_domain_show(void) +smb_domain_show(void) { char buf[MAXPATHLEN]; char *p; @@ -449,8 +449,8 @@ } void -nt_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain, - nt_domain_t *di) +smb_domain_set_basic_info(char *sid, char *nb_domain, char *fq_domain, + smb_domain_t *di) { if (sid == NULL || nb_domain == NULL || fq_domain == NULL || di == NULL) @@ -464,31 +464,31 @@ } void -nt_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain, - char *forest, char *guid, nt_domain_t *di) +smb_domain_set_dns_info(char *sid, char *nb_domain, char *fq_domain, + char *forest, char *guid, smb_domain_t *di) { if (di == NULL || forest == NULL || guid == NULL) return; - nt_domain_set_basic_info(sid, nb_domain, fq_domain, di); + smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); (void) strlcpy(di->di_u.di_dns.ddi_forest, forest, MAXHOSTNAMELEN); (void) strlcpy(di->di_u.di_dns.ddi_guid, guid, UUID_PRINTABLE_STRING_LENGTH); } void -nt_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain, +smb_domain_set_trust_info(char *sid, char *nb_domain, char *fq_domain, uint32_t trust_dir, uint32_t trust_type, uint32_t trust_attrs, - nt_domain_t *di) + smb_domain_t *di) { smb_domain_trust_t *ti; if (di == NULL) return; - di->di_type = NT_DOMAIN_TRUSTED; + di->di_type = SMB_DOMAIN_TRUSTED; ti = &di->di_u.di_trust; - nt_domain_set_basic_info(sid, nb_domain, fq_domain, di); + smb_domain_set_basic_info(sid, nb_domain, fq_domain, di); ti->dti_trust_direction = trust_dir; ti->dti_trust_type = trust_type; ti->dti_trust_attrs = trust_attrs; @@ -498,7 +498,7 @@ * Remove the /var/run/smb/domains file. */ static void -nt_domain_unlink(void) +smb_domain_unlink(void) { char fname[MAXPATHLEN]; @@ -511,12 +511,12 @@ * Add an entry for the local domain to the domain cache */ static uint32_t -nt_domain_add_local(void) +smb_domain_add_local(void) { char *lsidstr; char hostname[NETBIOS_NAME_SZ]; char fq_name[MAXHOSTNAMELEN]; - nt_domain_t di; + smb_domain_t di; if ((lsidstr = smb_config_get_localsid()) == NULL) return (SMB_DOMAIN_NOMACHINE_SID); @@ -528,8 +528,8 @@ *fq_name = '\0'; (void) smb_getfqhostname(fq_name, MAXHOSTNAMELEN); - nt_domain_set_basic_info(lsidstr, hostname, fq_name, &di); - (void) nt_domain_add(NT_DOMAIN_LOCAL, &di); + smb_domain_set_basic_info(lsidstr, hostname, fq_name, &di); + (void) smb_domain_add(SMB_DOMAIN_LOCAL, &di); free(lsidstr); return (SMB_DOMAIN_SUCCESS); @@ -539,12 +539,12 @@ * Add an entry for the primary domain to the domain cache */ static uint32_t -nt_domain_add_primary(uint32_t secmode) +smb_domain_add_primary(uint32_t secmode) { char sidstr[SMB_SID_STRSZ]; char fq_name[MAXHOSTNAMELEN]; char nb_name[NETBIOS_NAME_SZ]; - nt_domain_t di; + smb_domain_t di; int rc; if (secmode != SMB_SECMODE_DOMAIN) @@ -559,8 +559,8 @@ return (SMB_DOMAIN_NODOMAIN_NAME); (void) smb_getfqdomainname(fq_name, MAXHOSTNAMELEN); - nt_domain_set_basic_info(sidstr, nb_name, fq_name, &di); - (void) nt_domain_add(NT_DOMAIN_PRIMARY, &di); + smb_domain_set_basic_info(sidstr, nb_name, fq_name, &di); + (void) smb_domain_add(SMB_DOMAIN_PRIMARY, &di); return (SMB_DOMAIN_SUCCESS); } @@ -577,8 +577,8 @@ return; } - list_create(&smb_dcache.dc_cache, sizeof (nt_domain_t), - offsetof(nt_domain_t, di_lnd)); + list_create(&smb_dcache.dc_cache, sizeof (smb_domain_t), + offsetof(smb_domain_t, di_lnd)); smb_dcache.dc_nops = 0; *smb_dcache.dc_server = '\0'; @@ -592,7 +592,7 @@ static void smb_dcache_flush(void) { - nt_domain_t *di; + smb_domain_t *di; (void) rw_wrlock(&smb_dcache.dc_cache_lck); while ((di = list_head(&smb_dcache.dc_cache)) != NULL) @@ -687,11 +687,11 @@ } static uint32_t -smb_dcache_add(nt_domain_t *di) +smb_dcache_add(smb_domain_t *di) { - nt_domain_t *dcnode; + smb_domain_t *dcnode; - if ((dcnode = malloc(sizeof (nt_domain_t))) == NULL) + if ((dcnode = malloc(sizeof (smb_domain_t))) == NULL) return (SMB_DOMAIN_NO_MEMORY); *dcnode = *di; @@ -706,7 +706,7 @@ } static void -smb_dcache_remove(nt_domain_t *di) +smb_dcache_remove(smb_domain_t *di) { list_remove(&smb_dcache.dc_cache, di); smb_sid_free(di->di_binsid); @@ -729,6 +729,11 @@ (void) mutex_unlock(&smb_dcache.dc_mtx); } +/* + * Waits for SMB_DCACHE_UPDATE_WAIT seconds if cache is in + * UPDATING state. Upon wake up returns true if cache is + * ready to be used, otherwise it returns false. + */ static boolean_t smb_dcache_wait(void) { @@ -747,24 +752,77 @@ return (smb_dcache.dc_state == SMB_DCACHE_STATE_READY); } -static void +/* + * Transfers the cache into UPDATING state, this will ensure + * any read access to the cache will be stalled until the + * update is finished. This is to avoid providing incomplete, + * inconsistent or stale information. + * + * If another thread is already updating the cache, other + * callers will wait until cache is no longer in UPDATING + * state. The return code is decided based on the new + * state of the cache. + */ +static uint32_t smb_dcache_updating(void) { + uint32_t rc; + (void) mutex_lock(&smb_dcache.dc_mtx); - if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) + switch (smb_dcache.dc_state) { + case SMB_DCACHE_STATE_READY: smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING; - else - assert(0); + rc = SMB_DOMAIN_SUCCESS; + break; + + case SMB_DCACHE_STATE_UPDATING: + while (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) + (void) cond_wait(&smb_dcache.dc_cv, + &smb_dcache.dc_mtx); + + if (smb_dcache.dc_state == SMB_DCACHE_STATE_READY) { + smb_dcache.dc_state = SMB_DCACHE_STATE_UPDATING; + rc = SMB_DOMAIN_SUCCESS; + } else { + rc = SMB_DOMAIN_NO_CACHE; + } + break; + + case SMB_DCACHE_STATE_NONE: + case SMB_DCACHE_STATE_DESTROYING: + rc = SMB_DOMAIN_NO_CACHE; + break; + + default: + break; + } + (void) mutex_unlock(&smb_dcache.dc_mtx); + return (rc); } +/* + * Transfers the cache from UPDATING to READY state. + * + * Nothing will happen if the cache is no longer available + * or it is being destroyed. + */ static void smb_dcache_ready(void) { (void) mutex_lock(&smb_dcache.dc_mtx); - if (smb_dcache.dc_state == SMB_DCACHE_STATE_UPDATING) + switch (smb_dcache.dc_state) { + case SMB_DCACHE_STATE_UPDATING: smb_dcache.dc_state = SMB_DCACHE_STATE_READY; - else + (void) cond_broadcast(&smb_dcache.dc_cv); + break; + + case SMB_DCACHE_STATE_NONE: + case SMB_DCACHE_STATE_DESTROYING: + break; + + default: assert(0); + } (void) mutex_unlock(&smb_dcache.dc_mtx); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmb/common/smb_info.c --- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c Mon Oct 05 11:03:34 2009 -0700 @@ -48,6 +48,18 @@ static mutex_t seqnum_mtx; /* + * IPC connection information that may be passed to the SMB Redirector. + */ +typedef struct { + char user[SMB_USERNAME_MAXLEN]; + uint8_t passwd[SMBAUTH_HASH_SZ]; +} smb_ipc_t; + +static smb_ipc_t ipc_info; +static smb_ipc_t ipc_orig_info; +static rwlock_t smb_ipc_lock; + +/* * Some older clients (Windows 98) only handle the low byte * of the max workers value. If the low byte is less than * SMB_PI_MAX_WORKERS_MIN set it to SMB_PI_MAX_WORKERS_MIN. @@ -282,6 +294,108 @@ return (rc); } +static int +smb_get_machine_passwd(uint8_t *buf, size_t buflen) +{ + char pwd[SMB_PASSWD_MAXLEN + 1]; + int rc; + + if (buflen < SMBAUTH_HASH_SZ) + return (-1); + + rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); + if ((rc != SMBD_SMF_OK) || *pwd == '\0') + return (-1); + + if (smb_auth_ntlm_hash(pwd, buf) != 0) + return (-1); + + return (rc); +} + +/* + * Set up IPC connection credentials. + */ +void +smb_ipc_init(void) +{ + int rc; + + (void) rw_wrlock(&smb_ipc_lock); + bzero(&ipc_info, sizeof (smb_ipc_t)); + bzero(&ipc_orig_info, sizeof (smb_ipc_t)); + + (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); + rc = smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); + if (rc != 0) + *ipc_info.passwd = 0; + (void) rw_unlock(&smb_ipc_lock); + +} + +/* + * Set the IPC username and password hash in memory. If the domain + * join succeeds, the credentials will be committed for use with + * authenticated IPC. Otherwise, they should be rolled back. + */ +void +smb_ipc_set(char *plain_user, uint8_t *passwd_hash) +{ + (void) rw_wrlock(&smb_ipc_lock); + (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); + (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); + (void) rw_unlock(&smb_ipc_lock); + +} + +/* + * Save the host credentials to be used for authenticated IPC. + * The credentials are also saved to the original IPC info as + * rollback data in case the join domain process fails later. + */ +void +smb_ipc_commit(void) +{ + (void) rw_wrlock(&smb_ipc_lock); + (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); + (void) smb_get_machine_passwd(ipc_info.passwd, SMBAUTH_HASH_SZ); + (void) memcpy(&ipc_orig_info, &ipc_info, sizeof (smb_ipc_t)); + (void) rw_unlock(&smb_ipc_lock); +} + +/* + * Restore the original credentials + */ +void +smb_ipc_rollback(void) +{ + (void) rw_wrlock(&smb_ipc_lock); + (void) strlcpy(ipc_info.user, ipc_orig_info.user, + sizeof (ipc_info.user)); + (void) memcpy(ipc_info.passwd, ipc_orig_info.passwd, + sizeof (ipc_info.passwd)); + (void) rw_unlock(&smb_ipc_lock); +} + +void +smb_ipc_get_user(char *buf, size_t buflen) +{ + (void) rw_rdlock(&smb_ipc_lock); + (void) strlcpy(buf, ipc_info.user, buflen); + (void) rw_unlock(&smb_ipc_lock); +} + +void +smb_ipc_get_passwd(uint8_t *buf, size_t buflen) +{ + if (buflen < SMBAUTH_HASH_SZ) + return; + + (void) rw_rdlock(&smb_ipc_lock); + (void) memcpy(buf, ipc_info.passwd, SMBAUTH_HASH_SZ); + (void) rw_unlock(&smb_ipc_lock); +} + /* * smb_match_netlogon_seqnum * diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmb/common/smb_sam.c --- a/usr/src/lib/smbsrv/libsmb/common/smb_sam.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_sam.c Mon Oct 05 11:03:34 2009 -0700 @@ -96,7 +96,7 @@ smb_sam_lookup_name(char *domain, char *name, uint16_t type, smb_account_t *account) { - nt_domain_t di; + smb_domain_t di; smb_sid_t *sid; uint32_t status; smb_lwka_t *lwka; @@ -104,15 +104,15 @@ bzero(account, sizeof (smb_account_t)); if (domain != NULL) { - if (!nt_domain_lookup_name(domain, &di) || - (di.di_type != NT_DOMAIN_LOCAL)) + if (!smb_domain_lookup_name(domain, &di) || + (di.di_type != SMB_DOMAIN_LOCAL)) return (NT_STATUS_NOT_FOUND); /* Only Netbios hostname is accepted */ if (utf8_strcasecmp(domain, di.di_nbname) != 0) return (NT_STATUS_NONE_MAPPED); } else { - if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di)) + if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } @@ -209,7 +209,7 @@ smb_passwd_t smbpw; smb_group_t grp; smb_lwka_t *lwka; - nt_domain_t di; + smb_domain_t di; uint32_t rid; uid_t id; int id_type; @@ -217,7 +217,7 @@ bzero(account, sizeof (smb_account_t)); - if (!nt_domain_lookup_type(NT_DOMAIN_LOCAL, &di)) + if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); if (smb_sid_cmp(sid, di.di_binsid)) { @@ -362,17 +362,17 @@ * in /var/smb/smbgroup.db */ int -smb_sam_grp_cnt(nt_domain_type_t dtype) +smb_sam_grp_cnt(smb_domain_type_t dtype) { int grpcnt; int rc; switch (dtype) { - case NT_DOMAIN_BUILTIN: + case SMB_DOMAIN_BUILTIN: rc = smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &grpcnt); break; - case NT_DOMAIN_LOCAL: + case SMB_DOMAIN_LOCAL: rc = smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &grpcnt); break; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/libsmbns.h --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h Mon Oct 05 11:03:34 2009 -0700 @@ -37,8 +37,6 @@ typedef struct smb_ads_handle { - char *user; /* admin user to create share in ADS */ - char *pwd; /* user password */ char *domain; /* ADS domain */ char *domain_dn; /* domain in Distinquish Name format */ char *ip_addr; /* ip addr in string format */ @@ -103,14 +101,13 @@ extern void dyndns_update_zones(void); extern void dyndns_clear_zones(void); -/* Kerberos initialization function */ -extern int smb_kinit(char *, char *); +/* Kerberos cache management function */ extern int smb_ccache_init(char *, char *); extern void smb_ccache_remove(char *); /* NETBIOS Functions */ extern int smb_netbios_start(void); -extern void smb_netbios_shutdown(void); +extern void smb_netbios_stop(void); extern void smb_netbios_name_reconfig(void); /* Browser Functions */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/mapfile-vers --- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers Mon Oct 05 11:03:34 2009 -0700 @@ -62,10 +62,9 @@ smb_browser_reconfig; smb_ccache_init; smb_ccache_remove; - smb_kinit; smb_netbios_name_reconfig; smb_netbios_start; - smb_netbios_shutdown; + smb_netbios_stop; local: *; }; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c Mon Oct 05 11:03:34 2009 -0700 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -44,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -176,7 +177,6 @@ } smb_ads_host_list_t; static smb_ads_handle_t *smb_ads_open_main(char *, char *, char *); -static int smb_ads_bind(smb_ads_handle_t *); static int smb_ads_add_computer(smb_ads_handle_t *, int, char *); static int smb_ads_modify_computer(smb_ads_handle_t *, int, char *); static int smb_ads_computer_op(smb_ads_handle_t *, int, int, char *); @@ -595,7 +595,7 @@ /* * smb_ads_hlist_alloc */ -smb_ads_host_list_t * +static smb_ads_host_list_t * smb_ads_hlist_alloc(int count) { int size; @@ -1034,6 +1034,24 @@ return (smb_ads_open_main(domain, NULL, NULL)); } +static int +smb_ads_saslcallback(LDAP *ld, unsigned flags, void *defaults, void *prompts) +{ + NOTE(ARGUNUSED(ld, defaults)); + sasl_interact_t *interact; + + if (prompts == NULL || flags != LDAP_SASL_INTERACTIVE) + return (LDAP_PARAM_ERROR); + + /* There should be no extra arguemnts for SASL/GSSAPI authentication */ + for (interact = prompts; interact->id != SASL_CB_LIST_END; + interact++) { + interact->result = NULL; + interact->len = 0; + } + return (LDAP_SUCCESS); +} + /* * smb_ads_open_main * Open a LDAP connection to an ADS server. @@ -1048,7 +1066,7 @@ * After the LDAP connection, the LDAP version will be set to 3 using * ldap_set_option(). * - * The smb_ads_bind() routine is also called before the ADS handle is returned. + * The LDAP connection is bound before the ADS handle is returned. * Parameters: * domain - fully-qualified domain name * user - the user account for whom the Kerberos TGT ticket and ADS @@ -1066,6 +1084,14 @@ LDAP *ld; int version = 3; smb_ads_host_info_t *ads_host = NULL; + int rc; + + if (user != NULL) { + if (smb_kinit(user, password) == 0) + return (NULL); + user = NULL; + password = NULL; + } ads_host = smb_ads_find_host(domain, NULL); if (ads_host == NULL) @@ -1097,8 +1123,6 @@ (void) ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); ah->ld = ld; - ah->user = (user) ? strdup(user) : NULL; - ah->pwd = (password) ? strdup(password) : NULL; ah->domain = strdup(domain); if (ah->domain == NULL) { @@ -1133,7 +1157,11 @@ } (void) mutex_unlock(&smb_ads_cfg.c_mtx); - if (smb_ads_bind(ah) == -1) { + rc = ldap_sasl_interactive_bind_s(ah->ld, "", "GSSAPI", NULL, NULL, + LDAP_SASL_INTERACTIVE, &smb_ads_saslcallback, NULL); + if (rc != LDAP_SUCCESS) { + syslog(LOG_ERR, "ldal_sasl_interactive_bind_s failed (%s)", + ldap_err2string(rc)); smb_ads_close(ah); free(ads_host); return (NULL); @@ -1155,22 +1183,12 @@ void smb_ads_close(smb_ads_handle_t *ah) { - int len; - if (ah == NULL) return; /* close and free connection resources */ if (ah->ld) (void) ldap_unbind(ah->ld); - free(ah->user); - if (ah->pwd) { - len = strlen(ah->pwd); - /* zero out the memory that contains user's password */ - if (len > 0) - bzero(ah->pwd, len); - free(ah->pwd); - } free(ah->domain); free(ah->domain_dn); free(ah->hostname); @@ -1179,31 +1197,6 @@ } /* - * smb_ads_display_stat - * Display error message for GSS-API routines. - * Parameters: - * maj: GSS major status - * min: GSS minor status - * Returns: - * None - */ -static void -smb_ads_display_stat(OM_uint32 maj, OM_uint32 min) -{ - gss_buffer_desc msg; - OM_uint32 msg_ctx = 0; - OM_uint32 min2; - (void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - smb_tracef("major status: %s", (char *)msg.value); - (void) gss_release_buffer(&min2, &msg); - (void) gss_display_status(&min2, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - smb_tracef("minor status: %s", (char *)msg.value); - (void) gss_release_buffer(&min2, &msg); -} - -/* * smb_ads_alloc_attr * * Since the attrs is a null-terminated array, all elements @@ -1282,290 +1275,6 @@ } /* - * smb_ads_acquire_cred - * Called by smb_ads_bind() to get a handle to administrative user's credential - * stored locally on the system. The credential is the TGT. If the attempt at - * getting handle fails then a second attempt will be made after getting a - * new TGT. - * Please look at smb_ads_bind() for more information. - * - * Paramters: - * ah : handle to ADS server - * kinit_retry: if 0 then a second attempt will be made to get handle to the - * credential if the first attempt fails - * Returns: - * cred_handle: handle to the administrative user's credential (TGT) - * oid : contains Kerberos 5 object identifier - * kinit_retry: A 1 indicates that a second attempt has been made to get - * handle to the credential and no further attempts can be made - * -1 : error - * 0 : success - */ -static int -smb_ads_acquire_cred(smb_ads_handle_t *ah, gss_cred_id_t *cred_handle, - gss_OID *oid, int *kinit_retry) -{ - return (krb5_acquire_cred_kinit(ah->user, ah->pwd, cred_handle, oid, - kinit_retry, "ads")); -} - -/* - * smb_ads_establish_sec_context - * Called by smb_ads_bind() to establish a security context to an LDAP service - * on an ADS server. If the attempt at establishing the security context fails - * then a second attempt will be made by smb_ads_bind() if a new TGT has not - * been already obtained in ads_acquire_cred. The second attempt, if allowed, - * will obtained a new TGT here and a new handle to the credential will also be - * obtained in ads_acquire_cred. LDAP SASL bind is used to send and receive - * the GSS tokens to and from the ADS server. - * Please look at ads_bind for more information. - * Paramters: - * ah : handle to ADS server - * cred_handle : handle to administrative user's credential (TGT) - * oid : Kerberos 5 object identifier - * kinit_retry : if 0 then a second attempt can be made to establish a - * security context with ADS server if first attempt fails - * Returns: - * gss_context : security context to ADS server - * sercred : encrypted ADS server's supported security layers - * do_acquire_cred: if 1 then a second attempt will be made to establish a - * security context with ADS server after getting a new - * handle to the user's credential - * kinit_retry : if 1 then a second attempt will be made to establish a - * a security context and no further attempts can be made - * -1 : error - * 0 : success - */ -static int -smb_ads_establish_sec_context(smb_ads_handle_t *ah, gss_ctx_id_t *gss_context, - gss_cred_id_t cred_handle, gss_OID oid, struct berval **sercred, - int *kinit_retry, int *do_acquire_cred) -{ - OM_uint32 maj, min, time_rec; - char service_name[SMB_ADS_MAXBUFLEN]; - gss_buffer_desc send_tok, service_buf; - gss_name_t target_name; - gss_buffer_desc input; - gss_buffer_desc *inputptr; - struct berval cred; - OM_uint32 ret_flags; - int stat; - int gss_flags; - - (void) snprintf(service_name, SMB_ADS_MAXBUFLEN, "ldap@%s", - ah->hostname); - service_buf.value = service_name; - service_buf.length = strlen(service_name)+1; - if ((maj = gss_import_name(&min, &service_buf, - (gss_OID) gss_nt_service_name, - &target_name)) != GSS_S_COMPLETE) { - smb_ads_display_stat(maj, min); - if (oid != GSS_C_NO_OID) - (void) gss_release_oid(&min, &oid); - return (-1); - } - - *gss_context = GSS_C_NO_CONTEXT; - *sercred = NULL; - inputptr = GSS_C_NO_BUFFER; - gss_flags = GSS_C_MUTUAL_FLAG; - do { - if (krb5_establish_sec_ctx_kinit(ah->user, ah->pwd, - cred_handle, gss_context, target_name, oid, - gss_flags, inputptr, &send_tok, - &ret_flags, &time_rec, kinit_retry, - do_acquire_cred, &maj, "ads") == -1) { - if (oid != GSS_C_NO_OID) - (void) gss_release_oid(&min, &oid); - (void) gss_release_name(&min, &target_name); - return (-1); - } - - cred.bv_val = send_tok.value; - cred.bv_len = send_tok.length; - if (*sercred) { - ber_bvfree(*sercred); - *sercred = NULL; - } - stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI", - &cred, NULL, NULL, sercred); - if (stat != LDAP_SUCCESS && - stat != LDAP_SASL_BIND_IN_PROGRESS) { - syslog(LOG_NOTICE, "ldap_sasl_bind: %s", - ldap_err2string(stat)); - if (oid != GSS_C_NO_OID) - (void) gss_release_oid(&min, &oid); - (void) gss_release_name(&min, &target_name); - (void) gss_release_buffer(&min, &send_tok); - return (-1); - } - input.value = (*sercred)->bv_val; - input.length = (*sercred)->bv_len; - inputptr = &input; - if (send_tok.length > 0) - (void) gss_release_buffer(&min, &send_tok); - } while (maj != GSS_S_COMPLETE); - - if (oid != GSS_C_NO_OID) - (void) gss_release_oid(&min, &oid); - (void) gss_release_name(&min, &target_name); - - return (0); -} - -/* - * smb_ads_negotiate_sec_layer - * Call by smb_ads_bind() to negotiate additional security layer for further - * communication after security context establishment. No additional security - * is needed so a "no security layer" is negotiated. The security layer is - * described in the SASL RFC 2478 and this step is needed for secure LDAP - * binding. LDAP SASL bind is used to send and receive the GSS tokens to and - * from the ADS server. - * Please look at smb_ads_bind for more information. - * - * Paramters: - * ah : handle to ADS server - * gss_context: security context to ADS server - * sercred : encrypted ADS server's supported security layers - * Returns: - * -1 : error - * 0 : success - */ -static int -smb_ads_negotiate_sec_layer(smb_ads_handle_t *ah, gss_ctx_id_t gss_context, - struct berval *sercred) -{ - OM_uint32 maj, min; - gss_buffer_desc unwrap_inbuf, unwrap_outbuf; - gss_buffer_desc wrap_inbuf, wrap_outbuf; - int conf_state, sec_layer; - char auth_id[5]; - struct berval cred; - int stat; - gss_qop_t qt; - - /* check for server supported security layer */ - unwrap_inbuf.value = sercred->bv_val; - unwrap_inbuf.length = sercred->bv_len; - if ((maj = gss_unwrap(&min, gss_context, - &unwrap_inbuf, &unwrap_outbuf, - &conf_state, &qt)) != GSS_S_COMPLETE) { - smb_ads_display_stat(maj, min); - if (sercred) - ber_bvfree(sercred); - return (-1); - } - sec_layer = *((char *)unwrap_outbuf.value); - (void) gss_release_buffer(&min, &unwrap_outbuf); - if (!(sec_layer & 1)) { - if (sercred) - ber_bvfree(sercred); - return (-1); - } - if (sercred) ber_bvfree(sercred); - - /* no security layer needed after successful binding */ - auth_id[0] = 0x01; - - /* byte 2-4: max client recv size in network byte order */ - auth_id[1] = 0x00; - auth_id[2] = 0x40; - auth_id[3] = 0x00; - wrap_inbuf.value = auth_id; - wrap_inbuf.length = 4; - conf_state = 0; - if ((maj = gss_wrap(&min, gss_context, conf_state, 0, &wrap_inbuf, - &conf_state, &wrap_outbuf)) != GSS_S_COMPLETE) { - smb_ads_display_stat(maj, min); - return (-1); - } - - cred.bv_val = wrap_outbuf.value; - cred.bv_len = wrap_outbuf.length; - sercred = NULL; - stat = ldap_sasl_bind_s(ah->ld, NULL, "GSSAPI", &cred, NULL, NULL, - &sercred); - if (stat != LDAP_SUCCESS && stat != LDAP_SASL_BIND_IN_PROGRESS) { - syslog(LOG_NOTICE, "ldap_sasl_bind: %s", - ldap_err2string(stat)); - (void) gss_release_buffer(&min, &wrap_outbuf); - return (-1); - } - - (void) gss_release_buffer(&min, &wrap_outbuf); - if (sercred) - ber_bvfree(sercred); - - return (0); -} - -/* - * smb_ads_bind - * Use secure binding to bind to ADS server. - * Use GSS-API with Kerberos 5 as the security mechanism and LDAP SASL with - * Kerberos 5 as the security mechanisn to authenticate, obtain a security - * context, and securely bind an administrative user so that other LDAP - * commands can be used, i.e. add and delete. - * - * To obtain the security context, a Kerberos ticket-granting ticket (TGT) - * for the user is needed to obtain a ticket for the LDAP service. To get - * a TGT for the user, the username and password is needed. Once a TGT is - * obtained then it will be stored locally and used until it is expired. - * This routine will automatically obtained a TGT for the first time or when - * it expired. LDAP SASL bind is then finally used to send GSS tokens to - * obtain a security context for the LDAP service on the ADS server. If - * there is any problem getting the security context then a new TGT will be - * obtain to try getting the security context once more. - * - * After the security context is obtain and established, the LDAP SASL bind - * is used to negotiate an additional security layer. No further security is - * needed so a "no security layer" is negotiated. After this the security - * context can be deleted and further LDAP commands can be sent to the ADS - * server until a LDAP unbind command is issued to the ADS server. - * Paramaters: - * ah: handle to ADS server - * Returns: - * -1: error - * 0: success - */ -static int -smb_ads_bind(smb_ads_handle_t *ah) -{ - OM_uint32 min; - gss_cred_id_t cred_handle; - gss_ctx_id_t gss_context; - gss_OID oid; - struct berval *sercred; - int kinit_retry, do_acquire_cred; - int rc = 0; - - kinit_retry = 0; - do_acquire_cred = 0; - -acquire_cred: - - if (smb_ads_acquire_cred(ah, &cred_handle, &oid, &kinit_retry)) - return (-1); - - if (smb_ads_establish_sec_context(ah, &gss_context, cred_handle, - oid, &sercred, &kinit_retry, &do_acquire_cred)) { - (void) gss_release_cred(&min, &cred_handle); - if (do_acquire_cred) { - do_acquire_cred = 0; - goto acquire_cred; - } - return (-1); - } - rc = smb_ads_negotiate_sec_layer(ah, gss_context, sercred); - - if (cred_handle != GSS_C_NO_CREDENTIAL) - (void) gss_release_cred(&min, &cred_handle); - (void) gss_delete_sec_context(&min, &gss_context, NULL); - - return ((rc) ? -1 : 0); -} - -/* * smb_ads_add_share * Call by smb_ads_publish_share to create share object in ADS. * This routine specifies the attributes of an ADS LDAP share object. The first diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Mon Oct 05 11:03:34 2009 -0700 @@ -23,6 +23,7 @@ * Use is subject to license terms. */ +#include #include #include #include @@ -38,10 +39,8 @@ #include #include - #include #include - #include #include @@ -83,8 +82,6 @@ static void smb_browser_infofree(void); - - void smb_browser_reconfig(void) { @@ -653,7 +650,7 @@ struct name_entry *result) { uint32_t ipaddr, mask, saddr; - struct addr_entry *addr; + addr_entry_t *addr; if (name == NULL) return (-1); @@ -692,7 +689,7 @@ result->addr_list.sin.sin_family = AF_INET; result->addr_list.sinlen = sizeof (result->addr_list.sin); result->addr_list.sin.sin_addr.s_addr = bcast; - result->addr_list.sin.sin_port = htons(DGM_SRVC_UDP_PORT); + result->addr_list.sin.sin_port = htons(IPPORT_NETBIOS_DGM); result->addr_list.forw = result->addr_list.back = &result->addr_list; return (0); } @@ -772,7 +769,7 @@ static void smb_browser_send_HostAnnouncement(smb_hostinfo_t *hinfo, uint32_t next_announcement, boolean_t remove, - struct addr_entry *addr, char suffix) + addr_entry_t *addr, char suffix) { smb_msgbuf_t mb; int offset, announce_len, data_length; @@ -801,9 +798,9 @@ } /* give some extra room */ - buffer = (unsigned char *)malloc(MAX_DATAGRAM_LENGTH * 2); - if (buffer == 0) { - syslog(LOG_ERR, "HostAnnouncement: resource shortage"); + buffer = malloc(MAX_DATAGRAM_LENGTH * 2); + if (buffer == NULL) { + syslog(LOG_DEBUG, "smb browser: HostAnnouncement: %m"); return; } @@ -824,7 +821,7 @@ * specifying a type of 0 just prior to shutting down, to allow it to * quickly be removed from the list of available servers. */ - if (remove || (nb_status.state & NETBIOS_SHUTTING_DOWN)) + if (remove || (!smb_netbios_running())) type = 0; else type = hinfo->hi_type; @@ -860,11 +857,11 @@ boolean_t h_found = B_FALSE; if (strcmp(mailbox, MAILSLOT_LANMAN) != 0) { - syslog(LOG_DEBUG, "smb_browse: Wrong Mailbox (%s)", mailbox); + syslog(LOG_DEBUG, "smb browser: wrong mailbox (%s)", mailbox); return; } - (void) sleep(delay); + smb_netbios_sleep(delay); (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); hinfo = list_head(&smb_binfo.bi_hlist); @@ -882,7 +879,7 @@ if (h_found) { next_announcement = hinfo->hi_nextannouce * 60 * 1000; smb_browser_send_HostAnnouncement(hinfo, next_announcement, - B_FALSE, &datagram->src.addr_list, 0x1D); + B_FALSE, &datagram->src.addr_list, NBT_MB); } (void) rw_unlock(&smb_binfo.bi_hlist_rwl); } @@ -915,7 +912,7 @@ unsigned char *data; int datalen; - syslog(LOG_DEBUG, "smb_browse: packet_received"); + syslog(LOG_DEBUG, "smb browser: packet received"); smb_msgbuf_init(&mb, datagram->data, datagram->data_length, 0); rc = smb_msgbuf_decode(&mb, "Mb27.bwwwwb.w6.wwwwb.wwwws", @@ -939,7 +936,7 @@ &mailbox); /* Mailbox address */ if (rc < 0) { - syslog(LOG_ERR, "smb_browser_dispatch: decode error"); + syslog(LOG_ERR, "smb browser: decode error"); smb_msgbuf_term(&mb); free(datagram); return (0); @@ -972,7 +969,7 @@ break; default: - syslog(LOG_DEBUG, "smb_browse: invalid message_type(%d, %x)", + syslog(LOG_DEBUG, "smb browser: invalid message type(%d, %x)", message_type, message_type); break; } @@ -1064,7 +1061,7 @@ (void) utf8_strupr(resource_domain); /* domain<00> */ - smb_init_name_struct((unsigned char *)resource_domain, 0x00, + smb_init_name_struct((unsigned char *)resource_domain, NBT_WKSTA, 0, 0, 0, 0, 0, &name); entry = smb_name_find_name(&name); smb_name_unlock_name(entry); @@ -1072,9 +1069,9 @@ (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); hinfo = list_head(&smb_binfo.bi_hlist); while (hinfo) { - smb_init_name_struct((unsigned char *)resource_domain, 0x00, 0, - hinfo->hi_nic.nic_ip.a_ipv4, - htons(DGM_SRVC_UDP_PORT), NAME_ATTR_GROUP, + smb_init_name_struct((unsigned char *)resource_domain, + NBT_WKSTA, 0, hinfo->hi_nic.nic_ip.a_ipv4, + htons(IPPORT_NETBIOS_DGM), NAME_ATTR_GROUP, NAME_ATTR_LOCAL, &name); (void) smb_name_add_name(&name); @@ -1083,7 +1080,7 @@ (void) rw_unlock(&smb_binfo.bi_hlist_rwl); /* All our local master browsers */ - smb_init_name_struct((unsigned char *)resource_domain, 0x1D, + smb_init_name_struct((unsigned char *)resource_domain, NBT_MB, 0, 0, 0, 0, 0, &dest); entry = smb_name_find_name(&dest); @@ -1094,7 +1091,7 @@ rc = smb_browser_addr_of_subnet(entry, hinfo, &master); if (rc == 0) { syslog(LOG_DEBUG, - "smbd: Master browser found at %s", + "smb browser: master browser found at %s", inet_ntoa(master.addr_list.sin.sin_addr)); } hinfo = list_next(&smb_binfo.bi_hlist, hinfo); @@ -1106,10 +1103,11 @@ /* Domain master browser */ smb_init_name_struct((unsigned char *)resource_domain, - 0x1B, 0, 0, 0, 0, 0, &dest); + NBT_DMB, 0, 0, 0, 0, 0, &dest); if ((entry = smb_name_find_name(&dest)) != 0) { - syslog(LOG_DEBUG, "smbd: Domain Master browser for %s is %s", + syslog(LOG_DEBUG, + "smb browser: domain master browser for %s is %s", resource_domain, inet_ntoa(entry->addr_list.sin.sin_addr)); smb_name_unlock_name(entry); @@ -1161,8 +1159,9 @@ (void) utf8_strupr(hinfo->hi_nbname); /* 0x20: file server service */ smb_init_name_struct((unsigned char *)hinfo->hi_nbname, - 0x20, 0, hinfo->hi_nic.nic_ip.a_ipv4, - htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, + NBT_SERVER, 0, hinfo->hi_nic.nic_ip.a_ipv4, + htons(IPPORT_NETBIOS_DGM), + NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &hinfo->hi_netname); list_insert_tail(&smb_binfo.bi_hlist, hinfo); @@ -1186,17 +1185,17 @@ { struct name_entry name; struct name_entry *dest; - struct addr_entry addr; + addr_entry_t addr; char resource_domain[SMB_PI_MAX_DOMAIN]; smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, - remove, 0, 0x1D); + remove, 0, NBT_MB); if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) return; (void) utf8_strupr(resource_domain); - smb_init_name_struct((unsigned char *)resource_domain, 0x1D, + smb_init_name_struct((unsigned char *)resource_domain, NBT_MB, 0, 0, 0, 0, 0, &name); if ((dest = smb_name_find_name(&name))) { @@ -1204,16 +1203,16 @@ addr.forw = addr.back = &addr; smb_name_unlock_name(dest); smb_browser_send_HostAnnouncement(hinfo, hinfo->hi_interval, - remove, &addr, 0x1D); + remove, &addr, NBT_MB); } else { - smb_init_name_struct((unsigned char *)resource_domain, 0x1B, - 0, 0, 0, 0, 0, &name); + smb_init_name_struct((unsigned char *)resource_domain, + NBT_DMB, 0, 0, 0, 0, 0, &name); if ((dest = smb_name_find_name(&name))) { addr = dest->addr_list; addr.forw = addr.back = &addr; smb_name_unlock_name(dest); smb_browser_send_HostAnnouncement(hinfo, - remove, hinfo->hi_interval, &addr, 0x1B); + remove, hinfo->hi_interval, &addr, NBT_DMB); } } @@ -1235,61 +1234,24 @@ /* - * smb_browser_sleep - * - * Put browser in 1 minute sleep if netbios services are not - * shutting down and both name and datagram services are still - * running. It'll wake up after 1 minute or if one of the above - * conditions go false. It checks the conditions again and return - * 1 if everything is ok or 0 if browser shouldn't continue - * running. - */ -static boolean_t -smb_browser_sleep(void) -{ - boolean_t slept = B_FALSE; - timestruc_t to; - - (void) mutex_lock(&nb_status.mtx); - while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) && - (nb_status.state & NETBIOS_NAME_SVC_RUNNING) && - (nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING)) { - - if (slept) { - (void) mutex_unlock(&nb_status.mtx); - return (B_TRUE); - } - - to.tv_sec = 60; /* 1 minute */ - to.tv_nsec = 0; - (void) cond_reltimedwait(&nb_status.cv, &nb_status.mtx, &to); - slept = B_TRUE; - } - (void) mutex_unlock(&nb_status.mtx); - - return (B_FALSE); -} - -/* - * smb_browser_daemon - * - * Smb Netbios browser daemon. + * SMB NetBIOS Browser Service */ /*ARGSUSED*/ void * -smb_browser_daemon(void *arg) +smb_browser_service(void *arg) { smb_hostinfo_t *hinfo; smb_browser_infoinit(); smb_browser_config(); - smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 1); + smb_netbios_event(NETBIOS_EVENT_BROWSER_START); restart: do { (void) rw_rdlock(&smb_binfo.bi_hlist_rwl); hinfo = list_head(&smb_binfo.bi_hlist); + while (hinfo) { if (--hinfo->hi_nextannouce > 0 || hinfo->hi_nic.nic_bcast == 0) { @@ -1312,11 +1274,13 @@ hinfo = list_next(&smb_binfo.bi_hlist, hinfo); } + (void) rw_unlock(&smb_binfo.bi_hlist_rwl); - } while (smb_browser_sleep()); + smb_netbios_sleep(SECSPERMIN); /* 1 minute */ + } while (smb_netbios_running()); smb_browser_infoterm(); - smb_netbios_chg_status(NETBIOS_BROWSER_RUNNING, 0); + smb_netbios_event(NETBIOS_EVENT_BROWSER_STOP); return (0); } @@ -1367,8 +1331,8 @@ /* * smb_browser_infoinit * - * This function is called only once when browser daemon starts - * to initialize global smb_binfo structure + * This function is called only once when the browser starts + * to initialize the global smb_binfo structure. */ static void smb_browser_infoinit(void) @@ -1391,8 +1355,8 @@ /* * smb_browser_infoterm * - * This function is called only once when browser daemon stops - * to destruct smb_binfo structure + * This function is called only once when the browser stops + * to destroy the smb_binfo structure. */ static void smb_browser_infoterm(void) diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.c Mon Oct 05 11:03:34 2009 -0700 @@ -51,500 +51,100 @@ #include #include #include -#include #include -#include -#include #include -#include -#include #include -#include -#include #include - #include -static int krb5_acquire_cred_kinit_main(); - -typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type; - -struct k_opts { - /* in seconds */ - krb5_deltat starttime; - krb5_deltat lifetime; - krb5_deltat rlife; - - int forwardable; - int proxiable; - int addresses; - - int not_forwardable; - int not_proxiable; - int no_addresses; - - int verbose; - - char *principal_name; - char *principal_passwd; - char *service_name; - char *keytab_name; - char *k5_cache_name; - char *k4_cache_name; - - action_type action; -}; - -struct k5_data { - krb5_context ctx; - krb5_ccache cc; - krb5_principal me; - char *name; -}; - -static int -k5_begin(struct k_opts *opts, struct k5_data *k5) +int +smb_kinit(char *principal_name, char *principal_passwd) { - int code; - code = krb5_init_context(&k5->ctx); - if (code) { - return (code); - } - - if ((code = krb5_cc_default(k5->ctx, &k5->cc))) { - return (code); - } - - /* Use specified name */ - if ((code = krb5_parse_name(k5->ctx, opts->principal_name, &k5->me))) { - return (code); - } - - code = krb5_unparse_name(k5->ctx, k5->me, &k5->name); - if (code) { - return (code); - } - opts->principal_name = k5->name; - - return (0); -} + krb5_context ctx = NULL; + krb5_ccache cc = NULL; + krb5_principal me = NULL; + krb5_creds my_creds; + krb5_error_code code; + const char *errmsg = NULL; + const char *doing = NULL; -static void -k5_end(struct k5_data *k5) -{ - if (k5->name) - krb5_free_unparsed_name(k5->ctx, k5->name); - if (k5->me) - krb5_free_principal(k5->ctx, k5->me); - if (k5->cc) - krb5_cc_close(k5->ctx, k5->cc); - if (k5->ctx) - krb5_free_context(k5->ctx); - (void) memset(k5, 0, sizeof (*k5)); -} + assert(principal_name != NULL); + assert(principal_passwd != NULL); -static int -k5_kinit(struct k_opts *opts, struct k5_data *k5) -{ - int notix = 1; - krb5_keytab keytab = 0; - krb5_creds my_creds; - krb5_error_code code = 0; - krb5_get_init_creds_opt options; - const char *errmsg; - - krb5_get_init_creds_opt_init(&options); (void) memset(&my_creds, 0, sizeof (my_creds)); /* - * From this point on, we can goto cleanup because my_creds is - * initialized. + * From this point on, we can goto cleanup because the key variables + * are initialized. */ - if (opts->lifetime) - krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime); - if (opts->rlife) - krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife); - if (opts->forwardable) - krb5_get_init_creds_opt_set_forwardable(&options, 1); - if (opts->not_forwardable) - krb5_get_init_creds_opt_set_forwardable(&options, 0); - if (opts->proxiable) - krb5_get_init_creds_opt_set_proxiable(&options, 1); - if (opts->not_proxiable) - krb5_get_init_creds_opt_set_proxiable(&options, 0); - if (opts->addresses) { - krb5_address **addresses = NULL; - code = krb5_os_localaddr(k5->ctx, &addresses); - if (code != 0) { - errmsg = error_message(code); - syslog(LOG_ERR, "k5_kinit: getting local addresses " - "(%s)", errmsg); - goto cleanup; - } - krb5_get_init_creds_opt_set_address_list(&options, addresses); - } - if (opts->no_addresses) - krb5_get_init_creds_opt_set_address_list(&options, NULL); - - if ((opts->action == INIT_KT) && opts->keytab_name) { - code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); - if (code != 0) { - errmsg = error_message(code); - syslog(LOG_ERR, "k5_kinit: resolving keytab %s (%s)", - errmsg, opts->keytab_name); - goto cleanup; - } - } - switch (opts->action) { - case INIT_PW: - code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, - opts->principal_passwd, NULL, 0, opts->starttime, - opts->service_name, &options); - break; - case INIT_KT: - code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, - keytab, opts->starttime, opts->service_name, &options); - break; - case VALIDATE: - code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, - k5->cc, opts->service_name); - break; - case RENEW: - code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, - k5->cc, opts->service_name); - break; - } - + code = krb5_init_context(&ctx); if (code) { - char *doing = 0; - switch (opts->action) { - case INIT_PW: - case INIT_KT: - doing = "k5_kinit: getting initial credentials"; - break; - case VALIDATE: - doing = "k5_kinit: validating credentials"; - break; - case RENEW: - doing = "k5_kinit: renewing credentials"; - break; - } - - /* - * If got code == KRB5_AP_ERR_V4_REPLY && got_k4, we should - * let the user know that maybe he/she wants -4. - */ - if (code == KRB5KRB_AP_ERR_V4_REPLY) { - syslog(LOG_ERR, "%s\n" - "The KDC doesn't support v5. " - "You may want the -4 option in the future", doing); - return (1); - } else if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { - syslog(LOG_ERR, "%s (Password incorrect)", doing); - } else { - errmsg = error_message(code); - syslog(LOG_ERR, "%s (%s)", doing, errmsg); - } + doing = "initializing context"; goto cleanup; } - if (!opts->lifetime) { - /* We need to figure out what lifetime to use for Kerberos 4. */ - opts->lifetime = my_creds.times.endtime - - my_creds.times.authtime; - } - - code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me); - if (code) { - errmsg = error_message(code); - syslog(LOG_ERR, "k5_kinit: initializing cache %s (%s)", - opts->k5_cache_name ? opts->k5_cache_name : "", errmsg); + code = krb5_cc_default(ctx, &cc); + if (code != 0) { + doing = "resolve default credentials cache"; goto cleanup; } - code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds); - if (code) { - errmsg = error_message(code); - syslog(LOG_ERR, "k5_kinit: storing credentials (%s)", errmsg); + /* Use specified name */ + code = krb5_parse_name(ctx, principal_name, &me); + if (code != 0) { + doing = "parsing principal name"; goto cleanup; } - notix = 0; - - cleanup: - if (my_creds.client == k5->me) { - my_creds.client = 0; - } - krb5_free_cred_contents(k5->ctx, &my_creds); - if (keytab) - krb5_kt_close(k5->ctx, keytab); - return (notix?0:1); -} + code = krb5_get_init_creds_password(ctx, &my_creds, me, + principal_passwd, NULL, 0, (krb5_deltat)0, + NULL, NULL); + if (code != 0) { + doing = "getting initial credentials"; -int -smb_kinit(char *user, char *passwd) -{ - struct k_opts opts; - struct k5_data k5; - int authed_k5 = 0; - - assert(user); - assert(passwd); + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + errmsg = "Password incorrect"; + } - (void) memset(&opts, 0, sizeof (opts)); - opts.action = INIT_PW; - opts.principal_name = user; - opts.principal_passwd = passwd; + goto cleanup; + } - (void) memset(&k5, 0, sizeof (k5)); - - if (k5_begin(&opts, &k5) != 0) { - syslog(LOG_ERR, "NOT authenticated with Kerberos v5. " - "k5_begin failed\n"); - return (0); + code = krb5_cc_initialize(ctx, cc, me); + if (code != 0) { + doing = "initializing cache"; + goto cleanup; } - authed_k5 = k5_kinit(&opts, &k5); - if (authed_k5) - syslog(LOG_DEBUG, "Authenticated with Kerberos v5\n"); - else - syslog(LOG_DEBUG, "NOT authenticated with Kerberos v5\n"); - - k5_end(&k5); - - return (authed_k5); -} - -/* - * krb5_display_stat - * Display error message for GSS-API routines. - * Parameters: - * maj : GSS major status - * min : GSS minor status - * caller_mod: module name that calls this routine so that the module name - * can be displayed with the error messages - * Returns: - * None - */ -static void -krb5_display_stat(OM_uint32 maj, OM_uint32 min, char *caller_mod) -{ - gss_buffer_desc msg; - OM_uint32 msg_ctx = 0; - OM_uint32 min2; - (void) gss_display_status(&min2, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - syslog(LOG_ERR, "%s: major status error: %s\n", - caller_mod, (char *)msg.value); - (void) gss_release_buffer(&min2, &msg); - - (void) gss_display_status(&min2, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, - &msg_ctx, &msg); - syslog(LOG_ERR, "%s: minor status error: %s\n", - caller_mod, (char *)msg.value); - (void) gss_release_buffer(&min2, &msg); -} - -/* - * krb5_acquire_cred_kinit - * - * Wrapper for krb5_acquire_cred_kinit_main with mutex to protect credential - * cache file when calling krb5_acquire_cred or kinit. - */ - -int -krb5_acquire_cred_kinit(char *user, char *pwd, gss_cred_id_t *cred_handle, - gss_OID *oid, int *kinit_retry, char *caller_mod) -{ - int ret; - - ret = krb5_acquire_cred_kinit_main(user, pwd, - cred_handle, oid, kinit_retry, caller_mod); - return (ret); -} - -/* - * krb5_acquire_cred_kinit_main - * - * This routine is called by ADS module to get a handle to administrative - * user's credential stored locally on the system. The credential is the TGT. - * If the attempt at getting handle fails then a second attempt will be made - * after getting a new TGT. - * - * If there's no username then we must be using host credentials and we don't - * bother trying to acquire a credential for GSS_C_NO_NAME (which should be - * equivalent to using GSS_C_NO_CREDENTIAL, but it isn't in a very subtle way - * because mech_krb5 isn't so smart). Specifically mech_krb5 will try hard - * to get a non-expired TGT using the keytab if we're running as root (or fake - * it, using the special app_krb5_user_uid() function), but only when we use - * the default credential, as opposed to a credential for the default principal. - * - * Paramters: - * user : username to retrieve a handle to its credential - * pwd : password of username in case obtaining a new TGT is needed - * kinit_retry: if 0 then a second attempt will be made to get handle to the - * credential if the first attempt fails - * caller_mod : name of module that call this routine so that the module name - * can be included with error messages - * Returns: - * cred_handle: handle to the administrative user's credential (TGT) - * oid : contains Kerberos 5 object identifier - * kinit_retry: A 1 indicates that a second attempt has been made to get - * handle to the credential and no further attempts can be made - * -1 : error - * 0 : success - */ -static int -krb5_acquire_cred_kinit_main(char *user, char *pwd, gss_cred_id_t *cred_handle, - gss_OID *oid, int *kinit_retry, char *caller_mod) -{ - OM_uint32 maj, min; - gss_name_t desired_name = GSS_C_NO_NAME; - gss_OID_set desired_mechs; - gss_buffer_desc oidstr, name_buf; - char str[50], user_name[50]; - - *cred_handle = GSS_C_NO_CREDENTIAL; - *oid = GSS_C_NO_OID; - if (user == NULL || *user == '\0') - return (0); - - /* Object Identifier for Kerberos 5 */ - (void) strcpy(str, "{ 1 2 840 113554 1 2 2 }"); - oidstr.value = str; - oidstr.length = strlen(str); - if ((maj = gss_str_to_oid(&min, &oidstr, oid)) != GSS_S_COMPLETE) { - krb5_display_stat(maj, min, caller_mod); - return (-1); - } - if ((maj = gss_create_empty_oid_set(&min, &desired_mechs)) - != GSS_S_COMPLETE) { - krb5_display_stat(maj, min, caller_mod); - (void) gss_release_oid(&min, oid); - return (-1); - } - if ((maj = gss_add_oid_set_member(&min, *oid, &desired_mechs)) - != GSS_S_COMPLETE) { - krb5_display_stat(maj, min, caller_mod); - (void) gss_release_oid(&min, oid); - (void) gss_release_oid_set(&min, &desired_mechs); - return (-1); + code = krb5_cc_store_cred(ctx, cc, &my_creds); + if (code != 0) { + doing = "storing credentials"; + goto cleanup; } - (void) strcpy(user_name, user); - name_buf.value = user_name; - name_buf.length = strlen(user_name)+1; - if ((maj = gss_import_name(&min, &name_buf, GSS_C_NT_USER_NAME, - &desired_name)) != GSS_S_COMPLETE) { - krb5_display_stat(maj, min, caller_mod); - (void) gss_release_oid(&min, oid); - (void) gss_release_oid_set(&min, &desired_mechs); - return (-1); - } + /* SUCCESS! */ -acquire_cred: - if ((maj = gss_acquire_cred(&min, desired_name, 0, desired_mechs, - GSS_C_INITIATE, cred_handle, NULL, NULL)) != GSS_S_COMPLETE) { - if (!*kinit_retry && pwd != NULL && *pwd != '\0') { - (void) smb_kinit(user, pwd); - *kinit_retry = 1; - goto acquire_cred; - } else { - krb5_display_stat(maj, min, caller_mod); - (void) gss_release_oid(&min, oid); - (void) gss_release_oid_set(&min, &desired_mechs); - (void) gss_release_name(&min, &desired_name); - if (pwd == NULL || *pwd == '\0') { - /* See above */ - *cred_handle = GSS_C_NO_CREDENTIAL; - return (0); - } - return (-1); - } +cleanup: + if (code != 0) { + if (errmsg == NULL) + errmsg = error_message(code); + syslog(LOG_ERR, "k5_kinit: %s (%s)", doing, errmsg); } - (void) gss_release_oid_set(&min, &desired_mechs); - (void) gss_release_name(&min, &desired_name); - - return (0); -} + if (my_creds.client == me) { + my_creds.client = NULL; + } + krb5_free_cred_contents(ctx, &my_creds); -/* - * krb5_establish_sec_ctx_kinit - * - * This routine is called by the ADS module to establish a security - * context before ADS updates are allowed. If establishing a security context - * fails for any reason, a second attempt will be made after a new TGT is - * obtained. This routine is called many time as needed until a security - * context is established. - * - * The resources use for the security context must be released if security - * context establishment process fails. - * Parameters: - * user : user used in establishing a security context for. Is used for - * obtaining a new TGT for a second attempt at establishing - * security context - * pwd : password of above user - * cred_handle: a handle to the user credential (TGT) stored locally - * gss_context: initially set to GSS_C_NO_CONTEXT but will contain a handle - * to a security context - * target_name: contains service name to establish a security context with, - * ie ldap or dns - * gss_flags : flags used in establishing security context - * inputptr : initially set to GSS_C_NO_BUFFER but will be token data - * received from service's server to be processed to generate - * further token to be sent back to service's server during - * security context establishment - * kinit_retry: if 0 then a second attempt will be made to get handle to the - * credential if the first attempt fails - * caller_mod : name of module that call this routine so that the module name - * can be included with error messages - * Returns: - * gss_context : a handle to a security context - * out_tok : token data to be sent to service's server to establish - * security context - * ret_flags : return flags - * time_rec : valid time for security context, not currently used - * kinit_retry : A 1 indicates that a second attempt has been made to get - * handle to the credential and no further attempts can be - * made - * do_acquire_cred: A 1 indicates that a new handle to the local credential - * is needed for second attempt at security context - * establishment - * maj : major status code used if determining is security context - * establishment is successful - */ -int -krb5_establish_sec_ctx_kinit(char *user, char *pwd, - gss_cred_id_t cred_handle, gss_ctx_id_t *gss_context, - gss_name_t target_name, gss_OID oid, int gss_flags, - gss_buffer_desc *inputptr, gss_buffer_desc* out_tok, - OM_uint32 *ret_flags, OM_uint32 *time_rec, - int *kinit_retry, int *do_acquire_cred, - OM_uint32 *maj, char *caller_mod) -{ - OM_uint32 min; + if (me) + krb5_free_principal(ctx, me); + if (cc) + krb5_cc_close(ctx, cc); + if (ctx) + krb5_free_context(ctx); - *maj = gss_init_sec_context(&min, cred_handle, gss_context, - target_name, oid, gss_flags, 0, NULL, inputptr, NULL, - out_tok, ret_flags, time_rec); - if (*maj != GSS_S_COMPLETE && *maj != GSS_S_CONTINUE_NEEDED) { - if (*gss_context != NULL) - (void) gss_delete_sec_context(&min, gss_context, NULL); - - if ((user != NULL) && (pwd != NULL) && !*kinit_retry) { - (void) smb_kinit(user, pwd); - *kinit_retry = 1; - *do_acquire_cred = 1; - return (-1); - } else { - krb5_display_stat(*maj, min, caller_mod); - return (-1); - } - } - return (0); + return (code == 0); } /* diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_krb.h Mon Oct 05 11:03:34 2009 -0700 @@ -19,14 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _SMBSRV_SMB_KRB5_H -#define _SMBSRV_SMB_KRB5_H +#ifndef _SMBSRV_SMB_KRB_H +#define _SMBSRV_SMB_KRB_H -#include #include #ifdef __cplusplus @@ -45,19 +44,7 @@ SMBKRB5_SPN_IDX_MAX } smb_krb5_spn_idx_t; -extern gss_OID gss_nt_user_name; -extern gss_OID gss_nt_machine_uid_name; -extern gss_OID gss_nt_string_uid_name; -extern gss_OID gss_nt_service_name; -extern gss_OID gss_nt_exported_name; -extern gss_OID gss_nt_service_name_v2; - -int krb5_acquire_cred_kinit(char *, char *, gss_cred_id_t *, - gss_OID *, int *, char *); -int krb5_establish_sec_ctx_kinit(char *, char *, gss_cred_id_t, - gss_ctx_id_t *, gss_name_t, gss_OID, int, gss_buffer_desc *, - gss_buffer_desc *, OM_uint32 *, OM_uint32 *, int *, - int *, OM_uint32 *, char *); +int smb_kinit(char *, char *); char *smb_krb5_get_spn(smb_krb5_spn_idx_t idx, char *fqhost); char *smb_krb5_get_upn(char *spn, char *domain); int smb_krb5_ctx_init(krb5_context *ctx); @@ -76,4 +63,4 @@ } #endif -#endif /* _SMBSRV_SMB_KRB5_H */ +#endif /* _SMBSRV_SMB_KRB_H */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,175 +19,162 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Main startup code for SMB/NETBIOS and some utility routines * for the NETBIOS layer. */ +#include +#include #include #include #include #include #include #include - +#include +#include +#include #include -netbios_status_t nb_status; +#define SMB_NETBIOS_DUMP_FILE "netbios" -static pthread_t smb_nbns_thr; /* name service */ -static pthread_t smb_nbds_thr; /* dgram service */ -static pthread_t smb_nbts_thr; /* timer */ -static pthread_t smb_nbbs_thr; /* browser */ - -static void *smb_netbios_timer(void *); +static netbios_service_t nbtd; -void -smb_netbios_chg_status(uint32_t status, int set) -{ - (void) mutex_lock(&nb_status.mtx); - if (set) - nb_status.state |= status; - else - nb_status.state &= ~status; - (void) cond_broadcast(&nb_status.cv); - (void) mutex_unlock(&nb_status.mtx); -} +static void smb_netbios_shutdown(void); +static void *smb_netbios_service(void *); +static void smb_netbios_dump(void); -void -smb_netbios_shutdown(void) -{ - smb_netbios_chg_status(NETBIOS_SHUTTING_DOWN, 1); - - (void) pthread_join(smb_nbts_thr, 0); - (void) pthread_join(smb_nbbs_thr, 0); - (void) pthread_join(smb_nbns_thr, 0); - (void) pthread_join(smb_nbds_thr, 0); - - nb_status.state = NETBIOS_SHUT_DOWN; -} - +/* + * Start the NetBIOS services + */ int smb_netbios_start(void) { - int rc; - mutex_t *mp; - cond_t *cvp; + pthread_t tid; + pthread_attr_t attr; + int rc; - /* Startup Netbios named; port 137 */ - rc = pthread_create(&smb_nbns_thr, 0, - smb_netbios_name_service_daemon, 0); - if (rc) + if (smb_netbios_cache_init() < 0) return (-1); - mp = &nb_status.mtx; - cvp = &nb_status.cv; + (void) pthread_attr_init(&attr); + (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&tid, &attr, smb_netbios_service, NULL); + (void) pthread_attr_destroy(&attr); + return (rc); +} + +/* + * Stop the NetBIOS services + */ +void +smb_netbios_stop(void) +{ + char fname[MAXPATHLEN]; + + smb_netbios_event(NETBIOS_EVENT_STOP); + + (void) snprintf(fname, MAXPATHLEN, "%s/%s", + SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE); + (void) unlink(fname); - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_NAME_SVC_RUNNING | - NETBIOS_NAME_SVC_FAILED))) { - (void) cond_wait(cvp, mp); +} + +/* + * Launch the NetBIOS Name Service, Datagram and Browser services + * and then sit in a loop providing a 1 second resolution timer. + * The timer will: + * - update the netbios stats file every 10 minutes + * - clean the cache every 10 minutes + */ +/*ARGSUSED*/ +static void * +smb_netbios_service(void *arg) +{ + static uint32_t ticks = 0; + pthread_t tid; + int rc; + + smb_netbios_event(NETBIOS_EVENT_START); + + rc = pthread_create(&tid, NULL, smb_netbios_name_service, NULL); + if (rc != 0) { + smb_netbios_shutdown(); + return (NULL); } - if (nb_status.state & NETBIOS_NAME_SVC_FAILED) { - (void) mutex_unlock(mp); + smb_netbios_wait(NETBIOS_EVENT_NS_START); + if (smb_netbios_error()) { smb_netbios_shutdown(); - return (-1); + return (NULL); } - (void) mutex_unlock(mp); smb_netbios_name_config(); - /* Startup Netbios datagram service; port 138 */ - rc = pthread_create(&smb_nbds_thr, 0, - smb_netbios_datagram_service_daemon, 0); + rc = pthread_create(&tid, NULL, smb_netbios_datagram_service, NULL); if (rc != 0) { smb_netbios_shutdown(); - return (-1); - } - - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | - NETBIOS_DATAGRAM_SVC_FAILED))) { - (void) cond_wait(cvp, mp); - } - - if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { - (void) mutex_unlock(mp); - smb_netbios_shutdown(); - return (-1); - } - (void) mutex_unlock(mp); - - /* Startup Netbios browser service */ - rc = pthread_create(&smb_nbbs_thr, 0, smb_browser_daemon, 0); - if (rc) { - smb_netbios_shutdown(); - return (-1); + return (NULL); } - /* Startup Our internal, 1 second resolution, timer */ - rc = pthread_create(&smb_nbts_thr, 0, smb_netbios_timer, 0); - if (rc != 0) { + smb_netbios_wait(NETBIOS_EVENT_DGM_START); + if (smb_netbios_error()) { smb_netbios_shutdown(); - return (-1); - } - - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | - NETBIOS_TIMER_FAILED))) { - (void) cond_wait(cvp, mp); + return (NULL); } - if (nb_status.state & NETBIOS_TIMER_FAILED) { - (void) mutex_unlock(mp); + rc = pthread_create(&tid, NULL, smb_browser_service, NULL); + if (rc != 0) { smb_netbios_shutdown(); - return (-1); + return (NULL); } - (void) mutex_unlock(mp); - - return (0); -} -/*ARGSUSED*/ -static void * -smb_netbios_timer(void *arg) -{ - static unsigned int ticks = 0; + smb_netbios_event(NETBIOS_EVENT_TIMER_START); - smb_netbios_chg_status(NETBIOS_TIMER_RUNNING, 1); - - while ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) { + for (;;) { (void) sleep(1); ticks++; - if ((nb_status.state & NETBIOS_DATAGRAM_SVC_RUNNING) == 0) - break; - - if ((nb_status.state & NETBIOS_NAME_SVC_RUNNING) == 0) + if (!smb_netbios_running()) break; smb_netbios_datagram_tick(); smb_netbios_name_tick(); - /* every 10 minutes */ - if ((ticks % 600) == 0) + if ((ticks % 600) == 0) { + smb_netbios_event(NETBIOS_EVENT_DUMP); smb_netbios_cache_clean(); + } } - nb_status.state &= ~NETBIOS_TIMER_RUNNING; - if ((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) { - /* either name or datagram service has failed */ - smb_netbios_shutdown(); + smb_netbios_event(NETBIOS_EVENT_TIMER_STOP); + smb_netbios_shutdown(); + return (NULL); +} + +static void +smb_netbios_shutdown(void) +{ + (void) pthread_join(nbtd.nbs_browser.s_tid, 0); + (void) pthread_join(nbtd.nbs_dgm.s_tid, 0); + (void) pthread_join(nbtd.nbs_ns.s_tid, 0); + + nbtd.nbs_browser.s_tid = 0; + nbtd.nbs_dgm.s_tid = 0; + nbtd.nbs_ns.s_tid = 0; + + smb_netbios_cache_fini(); + + if (smb_netbios_error()) { + smb_netbios_event(NETBIOS_EVENT_RESET); + if (smb_netbios_start() != 0) + syslog(LOG_ERR, "netbios: restart failed"); } - - return (0); } int @@ -264,3 +251,283 @@ dest->addr_list.attributes = addr_attr; dest->addr_list.forw = dest->addr_list.back = &dest->addr_list; } + +void +smb_netbios_event(netbios_event_t event) +{ + static char *event_msg[] = { + "startup", + "shutdown", + "restart", + "name service started", + "name service stopped", + "datagram service started", + "datagram service stopped", + "browser service started", + "browser service stopped", + "timer service started", + "timer service stopped", + "error", + "dump" + }; + + (void) mutex_lock(&nbtd.nbs_mtx); + + if (event == NETBIOS_EVENT_DUMP) { + if (nbtd.nbs_last_event == NULL) + nbtd.nbs_last_event = event_msg[event]; + smb_netbios_dump(); + (void) mutex_unlock(&nbtd.nbs_mtx); + return; + } + + nbtd.nbs_last_event = event_msg[event]; + syslog(LOG_DEBUG, "netbios: %s", nbtd.nbs_last_event); + + switch (nbtd.nbs_state) { + case NETBIOS_STATE_INIT: + if (event == NETBIOS_EVENT_START) + nbtd.nbs_state = NETBIOS_STATE_RUNNING; + break; + + case NETBIOS_STATE_RUNNING: + switch (event) { + case NETBIOS_EVENT_NS_START: + nbtd.nbs_ns.s_tid = pthread_self(); + nbtd.nbs_ns.s_up = B_TRUE; + break; + case NETBIOS_EVENT_NS_STOP: + nbtd.nbs_ns.s_up = B_FALSE; + break; + case NETBIOS_EVENT_DGM_START: + nbtd.nbs_dgm.s_tid = pthread_self(); + nbtd.nbs_dgm.s_up = B_TRUE; + break; + case NETBIOS_EVENT_DGM_STOP: + nbtd.nbs_dgm.s_up = B_FALSE; + break; + case NETBIOS_EVENT_BROWSER_START: + nbtd.nbs_browser.s_tid = pthread_self(); + nbtd.nbs_browser.s_up = B_TRUE; + break; + case NETBIOS_EVENT_BROWSER_STOP: + nbtd.nbs_browser.s_up = B_FALSE; + break; + case NETBIOS_EVENT_TIMER_START: + nbtd.nbs_timer.s_tid = pthread_self(); + nbtd.nbs_timer.s_up = B_TRUE; + break; + case NETBIOS_EVENT_TIMER_STOP: + nbtd.nbs_timer.s_up = B_FALSE; + break; + case NETBIOS_EVENT_STOP: + nbtd.nbs_state = NETBIOS_STATE_CLOSING; + break; + case NETBIOS_EVENT_ERROR: + nbtd.nbs_state = NETBIOS_STATE_ERROR; + ++nbtd.nbs_errors; + break; + default: + break; + } + break; + + case NETBIOS_STATE_CLOSING: + case NETBIOS_STATE_ERROR: + default: + switch (event) { + case NETBIOS_EVENT_NS_STOP: + nbtd.nbs_ns.s_up = B_FALSE; + break; + case NETBIOS_EVENT_DGM_STOP: + nbtd.nbs_dgm.s_up = B_FALSE; + break; + case NETBIOS_EVENT_BROWSER_STOP: + nbtd.nbs_browser.s_up = B_FALSE; + break; + case NETBIOS_EVENT_TIMER_STOP: + nbtd.nbs_timer.s_up = B_FALSE; + break; + case NETBIOS_EVENT_STOP: + nbtd.nbs_state = NETBIOS_STATE_CLOSING; + break; + case NETBIOS_EVENT_RESET: + nbtd.nbs_state = NETBIOS_STATE_INIT; + break; + case NETBIOS_EVENT_ERROR: + ++nbtd.nbs_errors; + break; + default: + break; + } + break; + } + + smb_netbios_dump(); + (void) cond_broadcast(&nbtd.nbs_cv); + (void) mutex_unlock(&nbtd.nbs_mtx); +} + +void +smb_netbios_wait(netbios_event_t event) +{ + boolean_t *svc = NULL; + boolean_t desired_state; + + (void) mutex_lock(&nbtd.nbs_mtx); + + switch (event) { + case NETBIOS_EVENT_NS_START: + case NETBIOS_EVENT_NS_STOP: + svc = &nbtd.nbs_ns.s_up; + desired_state = + (event == NETBIOS_EVENT_NS_START) ? B_TRUE : B_FALSE; + break; + case NETBIOS_EVENT_DGM_START: + case NETBIOS_EVENT_DGM_STOP: + svc = &nbtd.nbs_dgm.s_up; + desired_state = + (event == NETBIOS_EVENT_DGM_START) ? B_TRUE : B_FALSE; + break; + case NETBIOS_EVENT_BROWSER_START: + case NETBIOS_EVENT_BROWSER_STOP: + svc = &nbtd.nbs_browser.s_up; + desired_state = + (event == NETBIOS_EVENT_BROWSER_START) ? B_TRUE : B_FALSE; + break; + default: + (void) mutex_unlock(&nbtd.nbs_mtx); + return; + } + + while (*svc != desired_state) { + if (nbtd.nbs_state != NETBIOS_STATE_RUNNING) + break; + + (void) cond_wait(&nbtd.nbs_cv, &nbtd.nbs_mtx); + } + + (void) mutex_unlock(&nbtd.nbs_mtx); +} + +void +smb_netbios_sleep(time_t seconds) +{ + timestruc_t reltimeout; + + (void) mutex_lock(&nbtd.nbs_mtx); + + if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) { + if (seconds == 0) + seconds = 1; + reltimeout.tv_sec = seconds; + reltimeout.tv_nsec = 0; + + (void) cond_reltimedwait(&nbtd.nbs_cv, + &nbtd.nbs_mtx, &reltimeout); + } + + (void) mutex_unlock(&nbtd.nbs_mtx); +} + +boolean_t +smb_netbios_running(void) +{ + boolean_t is_running; + + (void) mutex_lock(&nbtd.nbs_mtx); + + if (nbtd.nbs_state == NETBIOS_STATE_RUNNING) + is_running = B_TRUE; + else + is_running = B_FALSE; + + (void) mutex_unlock(&nbtd.nbs_mtx); + return (is_running); +} + +boolean_t +smb_netbios_error(void) +{ + boolean_t error; + + (void) mutex_lock(&nbtd.nbs_mtx); + + if (nbtd.nbs_state == NETBIOS_STATE_ERROR) + error = B_TRUE; + else + error = B_FALSE; + + (void) mutex_unlock(&nbtd.nbs_mtx); + return (error); +} + +/* + * Write the service state to /var/run/smb/netbios. + * + * This is a private interface. To update the file use: + * smb_netbios_event(NETBIOS_EVENT_DUMP); + */ +static void +smb_netbios_dump(void) +{ + static struct { + netbios_state_t state; + char *text; + } sm[] = { + { NETBIOS_STATE_INIT, "init" }, + { NETBIOS_STATE_RUNNING, "running" }, + { NETBIOS_STATE_CLOSING, "closing" }, + { NETBIOS_STATE_ERROR, "error" } + }; + + char fname[MAXPATHLEN]; + FILE *fp; + struct passwd *pwd; + struct group *grp; + uid_t uid; + gid_t gid; + char *last_event = "none"; + int i; + + (void) snprintf(fname, MAXPATHLEN, "%s/%s", + SMB_VARRUN_DIR, SMB_NETBIOS_DUMP_FILE); + + if ((fp = fopen(fname, "w")) == NULL) + return; + + pwd = getpwnam("root"); + grp = getgrnam("sys"); + uid = (pwd == NULL) ? 0 : pwd->pw_uid; + gid = (grp == NULL) ? 3 : grp->gr_gid; + + (void) lockf(fileno(fp), F_LOCK, 0); + (void) fchmod(fileno(fp), 0600); + (void) fchown(fileno(fp), uid, gid); + + if (nbtd.nbs_last_event) + last_event = nbtd.nbs_last_event; + + for (i = 0; i < sizeof (sm) / sizeof (sm[0]); ++i) { + if (nbtd.nbs_state == sm[i].state) { + (void) fprintf(fp, + "State %s (event: %s, errors: %u)\n", + sm[i].text, last_event, nbtd.nbs_errors); + break; + } + } + + (void) fprintf(fp, "Name Service %-7s (%u)\n", + nbtd.nbs_ns.s_up ? "up" : "down", nbtd.nbs_ns.s_tid); + (void) fprintf(fp, "Datagram Service %-7s (%u)\n", + nbtd.nbs_dgm.s_up ? "up" : "down", nbtd.nbs_dgm.s_tid); + (void) fprintf(fp, "Browser Service %-7s (%u)\n", + nbtd.nbs_browser.s_up ? "up" : "down", nbtd.nbs_browser.s_tid); + (void) fprintf(fp, "Timer Service %-7s (%u)\n", + nbtd.nbs_timer.s_up ? "up" : "down", nbtd.nbs_timer.s_tid); + + smb_netbios_cache_dump(fp); + + (void) lockf(fileno(fp), F_ULOCK, 0); + (void) fclose(fp); +} diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.h Mon Oct 05 11:03:34 2009 -0700 @@ -49,24 +49,45 @@ (e)->forw = 0; \ (e)->back = 0; -#define NETBIOS_NAME_SVC_LAUNCHED 0x00001 -#define NETBIOS_NAME_SVC_RUNNING 0x00002 -#define NETBIOS_NAME_SVC_FAILED 0x00004 - -#define NETBIOS_DATAGRAM_SVC_LAUNCHED 0x00010 -#define NETBIOS_DATAGRAM_SVC_RUNNING 0x00020 -#define NETBIOS_DATAGRAM_SVC_FAILED 0x00040 +typedef enum { + NETBIOS_EVENT_START = 0, + NETBIOS_EVENT_STOP, + NETBIOS_EVENT_RESET, + NETBIOS_EVENT_NS_START, + NETBIOS_EVENT_NS_STOP, + NETBIOS_EVENT_DGM_START, + NETBIOS_EVENT_DGM_STOP, + NETBIOS_EVENT_BROWSER_START, + NETBIOS_EVENT_BROWSER_STOP, + NETBIOS_EVENT_TIMER_START, + NETBIOS_EVENT_TIMER_STOP, + NETBIOS_EVENT_ERROR, + NETBIOS_EVENT_DUMP +} netbios_event_t; -#define NETBIOS_TIMER_LAUNCHED 0x00100 -#define NETBIOS_TIMER_RUNNING 0x00200 -#define NETBIOS_TIMER_FAILED 0x00400 +typedef enum { + NETBIOS_STATE_INIT = 0, + NETBIOS_STATE_RUNNING, + NETBIOS_STATE_CLOSING, + NETBIOS_STATE_ERROR +} netbios_state_t; + +typedef struct { + pthread_t s_tid; + boolean_t s_up; +} netbios_svc_t; -#define NETBIOS_BROWSER_LAUNCHED 0x01000 -#define NETBIOS_BROWSER_RUNNING 0x02000 -#define NETBIOS_BROWSER_FAILED 0x04000 - -#define NETBIOS_SHUTTING_DOWN 0x10000 -#define NETBIOS_SHUT_DOWN 0x20000 +typedef struct { + mutex_t nbs_mtx; + cond_t nbs_cv; + netbios_svc_t nbs_ns; + netbios_svc_t nbs_dgm; + netbios_svc_t nbs_browser; + netbios_svc_t nbs_timer; + netbios_state_t nbs_state; + uint32_t nbs_errors; + char *nbs_last_event; +} netbios_service_t; char smb_node_type; @@ -75,13 +96,6 @@ #define SMB_NODETYPE_M 'M' #define SMB_NODETYPE_H 'H' -typedef struct { - mutex_t mtx; - cond_t cv; - uint32_t state; -} netbios_status_t; -extern netbios_status_t nb_status; - /* * NAME service definitions */ @@ -614,14 +628,22 @@ #define NETBIOS_NAME_IS_STAR(name) \ (bcmp(name, "*\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NETBIOS_NAME_SZ) == 0) -void smb_netbios_chg_status(uint32_t status, int set); + +/* + * NetBIOS service state machine interface + */ +void smb_netbios_event(netbios_event_t); +void smb_netbios_wait(netbios_event_t); +void smb_netbios_sleep(time_t); +boolean_t smb_netbios_running(void); +boolean_t smb_netbios_error(void); /* * Name Cache Functions */ int smb_netbios_cache_init(void); void smb_netbios_cache_fini(void); -void smb_netbios_cache_dump(void); +void smb_netbios_cache_dump(FILE *fp); int smb_netbios_cache_count(void); void smb_netbios_cache_clean(void); void smb_netbios_cache_reset_ttl(void); @@ -640,13 +662,13 @@ int smb_netbios_cache_getfirst(nbcache_iter_t *); int smb_netbios_cache_getnext(nbcache_iter_t *); -void smb_netbios_name_dump(struct name_entry *entry); +void smb_netbios_name_dump(FILE *fp, struct name_entry *entry); void smb_netbios_name_logf(struct name_entry *entry); void smb_netbios_name_freeaddrs(struct name_entry *entry); struct name_entry *smb_netbios_name_dup(struct name_entry *, int); /* Name service functions */ -void *smb_netbios_name_service_daemon(void *); +void *smb_netbios_name_service(void *); void smb_init_name_struct(unsigned char *, char, unsigned char *, uint32_t, unsigned short, uint32_t, uint32_t, struct name_entry *); @@ -665,14 +687,14 @@ struct name_entry *); /* Datagram service functions */ -void *smb_netbios_datagram_service_daemon(void *); +void *smb_netbios_datagram_service(void *); int smb_netbios_datagram_send(struct name_entry *, struct name_entry *, unsigned char *, int); void smb_netbios_datagram_tick(void); /* browser functions */ void *smb_browser_dispatch(void *arg); -void *smb_browser_daemon(void *); +void *smb_browser_service(void *); int smb_browser_load_transact_header(unsigned char *, int, int, int, char *); /* Netlogon function */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -38,42 +36,37 @@ #define NETBIOS_HTAB_SZ 128 #define NETBIOS_HKEY_SZ (NETBIOS_NAME_SZ + NETBIOS_DOMAIN_NAME_MAX) -#define NETBIOS_NAMEBUF char namebuf[20] - #define NETBIOS_SAME_IP(addr1, addr2) \ ((addr1)->sin.sin_addr.s_addr == (addr2)->sin.sin_addr.s_addr) -int smb_netbios_name_debug = 0; - typedef char nb_key_t[NETBIOS_HKEY_SZ]; static HT_HANDLE *smb_netbios_cache = 0; static rwlock_t nb_cache_lock; -static char *smb_strname(struct name_entry *name, char *buf, int bufsize); +static void smb_strname(struct name_entry *name, char *buf, int bufsize); static void hash_callback(HT_ITEM *item); static int smb_netbios_match(const char *key1, const char *key2, size_t n); static void smb_netbios_cache_key(char *key, unsigned char *name, unsigned char *scope); int -smb_netbios_cache_init() +smb_netbios_cache_init(void) { (void) rw_wrlock(&nb_cache_lock); - if (smb_netbios_cache == 0) { + if (smb_netbios_cache == NULL) { smb_netbios_cache = ht_create_table(NETBIOS_HTAB_SZ, NETBIOS_HKEY_SZ, HTHF_FIXED_KEY); - if (smb_netbios_cache == 0) { - syslog(LOG_ERR, - "smbd: cannot create NetBIOS name cache"); + if (smb_netbios_cache == NULL) { + syslog(LOG_ERR, "nbns: cannot create name cache"); (void) rw_unlock(&nb_cache_lock); - return (0); + return (-1); } (void) ht_register_callback(smb_netbios_cache, hash_callback); ht_set_cmpfn(smb_netbios_cache, smb_netbios_match); } (void) rw_unlock(&nb_cache_lock); - return (1); + return (0); } void @@ -81,7 +74,7 @@ { (void) rw_wrlock(&nb_cache_lock); ht_destroy_table(smb_netbios_cache); - smb_netbios_cache = 0; + smb_netbios_cache = NULL; (void) rw_unlock(&nb_cache_lock); } @@ -201,8 +194,8 @@ smb_netbios_cache_lookup_addr(struct name_entry *name) { struct name_entry *entry = 0; - struct addr_entry *addr; - struct addr_entry *name_addr; + addr_entry_t *addr; + addr_entry_t *name_addr; HT_ITEM *item; nb_key_t key; @@ -234,8 +227,8 @@ smb_netbios_cache_insert(struct name_entry *name) { struct name_entry *entry; - struct addr_entry *addr; - struct addr_entry *name_addr; + addr_entry_t *addr; + addr_entry_t *name_addr; HT_ITEM *item; nb_key_t key; int rc; @@ -275,7 +268,7 @@ } } - if ((addr = malloc(sizeof (struct addr_entry))) != NULL) { + if ((addr = malloc(sizeof (addr_entry_t))) != NULL) { *addr = name->addr_list; entry->attributes |= addr->attributes; QUEUE_INSERT_TAIL(&entry->addr_list, addr); @@ -337,7 +330,7 @@ smb_netbios_cache_insert_list(struct name_entry *name) { struct name_entry entry; - struct addr_entry *addr; + addr_entry_t *addr; addr = &name->addr_list; do { @@ -361,8 +354,8 @@ smb_netbios_cache_update_entry(struct name_entry *entry, struct name_entry *name) { - struct addr_entry *addr; - struct addr_entry *name_addr; + addr_entry_t *addr; + addr_entry_t *name_addr; addr = &entry->addr_list; name_addr = &name->addr_list; @@ -442,7 +435,7 @@ void smb_netbios_cache_reset_ttl() { - struct addr_entry *addr; + addr_entry_t *addr; struct name_entry *name; HT_ITERATOR hti; HT_ITEM *item; @@ -524,7 +517,7 @@ smb_netbios_cache_refresh(name_queue_t *refq) { struct name_entry *name; - struct addr_entry *addr; + addr_entry_t *addr; HT_ITERATOR hti; HT_ITEM *item; @@ -608,7 +601,7 @@ void smb_netbios_name_freeaddrs(struct name_entry *entry) { - struct addr_entry *addr; + addr_entry_t *addr; if (entry == 0) return; @@ -637,19 +630,28 @@ } void -smb_netbios_cache_dump(void) +smb_netbios_cache_dump(FILE *fp) { struct name_entry *name; HT_ITERATOR hti; HT_ITEM *item; (void) rw_rdlock(&nb_cache_lock); + + if (ht_get_total_items(smb_netbios_cache) != 0) { + (void) fprintf(fp, "\n%-22s %-16s %-16s %s\n", + "Name", "Type", "Address", "TTL"); + (void) fprintf(fp, "%s%s\n", + "-------------------------------", + "------------------------------"); + } + item = ht_findfirst(smb_netbios_cache, &hti); while (item) { if (item->hi_data) { name = (struct name_entry *)item->hi_data; (void) mutex_lock(&name->mtx); - smb_netbios_name_dump(name); + smb_netbios_name_dump(fp, name); (void) mutex_unlock(&name->mtx); } item = ht_findnext(&hti); @@ -658,29 +660,28 @@ } void -smb_netbios_name_dump(struct name_entry *entry) +smb_netbios_name_dump(FILE *fp, struct name_entry *entry) { - struct addr_entry *addr; - int count = 0; + char buf[MAXHOSTNAMELEN]; + addr_entry_t *addr; + char *type; + int count = 0; - if (smb_netbios_name_debug == 0) - return; + smb_strname(entry, buf, sizeof (buf)); + type = (IS_UNIQUE(entry->attributes)) ? "UNIQUE" : "GROUP"; - syslog(LOG_DEBUG, "name='%15.15s<%02X>' scope='%s' attr=0x%x", - entry->name, entry->name[15], - entry->scope, entry->attributes); + (void) fprintf(fp, "%s %-6s (0x%04x) ", buf, type, entry->attributes); + addr = &entry->addr_list; do { - syslog(LOG_DEBUG, "addr_list[%d]:", count++); - syslog(LOG_DEBUG, " attributes = 0x%x", addr->attributes); - syslog(LOG_DEBUG, " conflict_timer = %d", - addr->conflict_timer); - syslog(LOG_DEBUG, " refresh_ttl = %d", addr->refresh_ttl); - syslog(LOG_DEBUG, " ttl = %d", addr->ttl); - syslog(LOG_DEBUG, " sin.sin_addr = %s", - inet_ntoa(addr->sin.sin_addr)); - syslog(LOG_DEBUG, " sin.sin_port = %d", addr->sin.sin_port); - syslog(LOG_DEBUG, " sin.sinlen = %d", addr->sinlen); + if (count == 0) + (void) fprintf(fp, "%-16s %d\n", + inet_ntoa(addr->sin.sin_addr), addr->ttl); + else + (void) fprintf(fp, "%-28s (0x%04x) %-16s %d\n", + " ", addr->attributes, + inet_ntoa(addr->sin.sin_addr), addr->ttl); + ++count; addr = addr->forw; } while (addr != &entry->addr_list); } @@ -688,16 +689,17 @@ void smb_netbios_name_logf(struct name_entry *entry) { - struct addr_entry *addr; - NETBIOS_NAMEBUF; + char namebuf[MAXHOSTNAMELEN]; + addr_entry_t *addr; - (void) smb_strname(entry, namebuf, sizeof (namebuf)); + smb_strname(entry, namebuf, sizeof (namebuf)); syslog(LOG_DEBUG, "%s flags=0x%x\n", namebuf, entry->attributes); addr = &entry->addr_list; do { - syslog(LOG_DEBUG, " %s ttl=%d flags=0x%x", + syslog(LOG_DEBUG, " %s ttl=%d flags=0x%x port=%d", inet_ntoa(addr->sin.sin_addr), - addr->ttl, addr->attributes); + addr->ttl, addr->attributes, + addr->sin.sin_port); addr = addr->forw; } while (addr && (addr != &entry->addr_list)); } @@ -716,8 +718,8 @@ struct name_entry * smb_netbios_name_dup(struct name_entry *entry, int alladdr) { - struct addr_entry *addr; - struct addr_entry *dup_addr; + addr_entry_t *addr; + addr_entry_t *dup_addr; struct name_entry *dup; int addr_cnt = 0; int size = 0; @@ -731,7 +733,7 @@ } size = sizeof (struct name_entry) + - (addr_cnt * sizeof (struct addr_entry)); + (addr_cnt * sizeof (addr_entry_t)); dup = (struct name_entry *)malloc(size); if (dup == 0) return (0); @@ -750,7 +752,7 @@ return (dup); /* LINTED - E_BAD_PTR_CAST_ALIGN */ - dup_addr = (struct addr_entry *)((unsigned char *)dup + + dup_addr = (addr_entry_t *)((unsigned char *)dup + sizeof (struct name_entry)); addr = entry->addr_list.forw; @@ -764,17 +766,22 @@ return (dup); } -static char * -smb_strname(struct name_entry *name, char *buf, int bufsize) +static void +smb_strname(struct name_entry *entry, char *buf, int bufsize) { - char *p; + char tmp[MAXHOSTNAMELEN]; + char *p; - (void) snprintf(buf, bufsize, "%15.15s", name->name); - p = strchr(buf, ' '); - if (p) - (void) snprintf(p, 5, "<%02X>", name->name[15]); + (void) snprintf(tmp, MAXHOSTNAMELEN, "%15.15s", entry->name); + if ((p = strchr(tmp, ' ')) != NULL) + *p = '\0'; - return (buf); + if (entry->scope[0] != '\0') { + (void) strlcat(tmp, ".", MAXHOSTNAMELEN); + (void) strlcat(tmp, (char *)entry->scope, MAXHOSTNAMELEN); + } + + (void) snprintf(buf, bufsize, "%-16s <%02X>", tmp, entry->name[15]); } static void diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c Mon Oct 05 11:03:34 2009 -0700 @@ -55,7 +55,7 @@ * The following are Defined Constants for the NetBIOS Datagram * Service: * - * - DGM_SRVC_UDP_PORT: the globally well-known UDP port allocated + * - IPPORT_NETBIOS_DGM: the globally well-known UDP port allocated * where the NetBIOS Datagram Service receives UDP packets. See * section 6, "Defined Constants", for its value. */ @@ -103,11 +103,12 @@ * * DATAGRAM SERVICE: * - * DGM_SRVC_UDP_PORT 138 (decimal) + * IPPORT_NETBIOS_DGM 138 (decimal) * * FRAGMENT_TO 2 seconds (default) */ +#include #include #include #include @@ -210,7 +211,7 @@ * half-ASCII, biased encoded name; * SOURCE_NAME = cat(source, SCOPE_ID); * SOURCE_IP = this nodes IP address; - * SOURCE_PORT = DGM_SRVC_UDP_PORT; + * SOURCE_PORT = IPPORT_NETBIOS_DGM; * * IF NetBIOS broadcast THEN * BEGIN @@ -318,7 +319,7 @@ { smb_inaddr_t ipaddr; size_t count, srclen, destlen, sinlen; - struct addr_entry *addr; + addr_entry_t *addr; struct sockaddr_in sin; char *buffer; char ha_source[NETBIOS_DOMAIN_NAME_MAX]; @@ -333,9 +334,8 @@ destlen = strlen(ha_dest) + 1; /* give some extra room */ - buffer = (char *)malloc(MAX_DATAGRAM_LENGTH * 4); - if (buffer == 0) { - syslog(LOG_ERR, "netbios: datagram send (resource shortage)"); + if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) { + syslog(LOG_ERR, "nbt datagram: send: %m"); return (-1); } @@ -399,7 +399,7 @@ { smb_inaddr_t ipaddr; size_t count, srclen, destlen, sinlen; - struct addr_entry *addr; + addr_entry_t *addr; struct sockaddr_in sin; char *buffer; char ha_source[NETBIOS_DOMAIN_NAME_MAX]; @@ -414,9 +414,8 @@ destlen = strlen(ha_dest) + 1; /* give some extra room */ - buffer = (char *)malloc(MAX_DATAGRAM_LENGTH * 4); - if (buffer == 0) { - syslog(LOG_ERR, "netbios: datagram send (resource shortage)"); + if ((buffer = malloc(MAX_DATAGRAM_LENGTH * 4)) == NULL) { + syslog(LOG_ERR, "nbt datagram: send_to_net: %m"); return (-1); } @@ -570,7 +569,7 @@ /* * Function: int smb_netbios_process_BPM_datagram(unsigned char *packet, - * struct addr_entry *addr) + * addr_entry_t *addr) * * Description from rfc1002: * @@ -797,7 +796,7 @@ (void) memcpy(&datagram->rawbuf[4], &datagram->src.addr_list.sin.sin_addr.s_addr, sizeof (uint32_t)); - BE_OUT16(&datagram->rawbuf[8], DGM_SRVC_UDP_PORT); + BE_OUT16(&datagram->rawbuf[8], IPPORT_NETBIOS_DGM); (void) sendto(datagram_sock, datagram->rawbuf, datagram->rawbytes, 0, @@ -812,180 +811,12 @@ free(datagram); } - /* - * smb_netbios_process_NBDD_datagram - * - * Description from rfc1002: - * - * - * 5.3.4. PROTOCOLS FOR THE NBDD - * - * The key to NetBIOS Datagram forwarding service is the packet - * delivered to the destination end node must have the same NetBIOS - * header as if the source end node sent the packet directly to the - * destination end node. Consequently, the NBDD does not reassemble - * NetBIOS Datagrams. It forwards the UDP packet as is. - * - * PROCEDURE datagram_packet(packet) - * - * (* - * * processing initiated by a incoming datagram service - * * packet on a NBDD node. - * *) - * - * BEGIN - * CASE packet type OF - * - * DATAGRAM SERVICE: - * BEGIN - * IF packet was sent as a directed - * NetBIOS datagram THEN - * BEGIN - * (* - * * provide group forwarding service - * * - * * Forward datagram to each member of the - * * group. Can forward via: - * * 1) get list of group members and send - * * the DATAGRAM SERVICE packet unicast - * * to each - * * 2) use Group Multicast, if available - * * 3) combination of 1) and 2) - * *) - * - * ... - * - * END - * - * ELSE - * BEGIN - * (* - * * provide broadcast forwarding service - * * - * * Forward datagram to every node in the - * * NetBIOS scope. Can forward via: - * * 1) get list of group members and send - * * the DATAGRAM SERVICE packet unicast - * * to each - * * 2) use Group Multicast, if available - * * 3) combination of 1) and 2) - * *) - * - * ... - * - * END - * END (* datagram service *) - * - * DATAGRAM ERROR: - * BEGIN - * (* - * * Should never receive these because Datagrams - * * forwarded have source end node IP address and - * * port in NetBIOS header. - * *) - * - * send DELETE NAME REQUEST with incorrect name and - * IP address to NetBIOS Name Server; - * - * END (* datagram error *) - * - * DATAGRAM QUERY REQUEST: - * BEGIN - * IF can send packet to DESTINATION_NAME THEN - * BEGIN - * (* - * * NBDD is able to relay Datagrams for - * * this name - * *) - * - * send POSITIVE DATAGRAM QUERY RESPONSE to - * REQUEST source IP address and UDP port - * with requests DGM_ID; - * END - * ELSE - * BEGIN - * (* - * * NBDD is NOT able to relay Datagrams for - * * this name - * *) - * - * send NEGATIVE DATAGRAM QUERY RESPONSE to - * REQUEST source IP address and UDP port - * - * with requests DGM_ID; - * END - * END (* datagram query request *) - * - * END (* case *) - * END (* procedure *) + * NetBIOS Datagram Service (port 138) */ - - -/* - * Function: int smb_netbios_datagram_service_daemon(void) - * - * Description: - * - * 4.4. DATAGRAM SERVICE PACKETS - * - * 4.4.1. NetBIOS DATAGRAM HEADER - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | MSG_TYPE | FLAGS | DGM_ID | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | SOURCE_IP | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | SOURCE_PORT | DGM_LENGTH | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | PACKET_OFFSET | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * MSG_TYPE values (in hexidecimal): - * - * 10 - DIRECT_UNIQUE DATAGRAM - * 11 - DIRECT_GROUP DATAGRAM - * 12 - BROADCAST DATAGRAM - * 13 - DATAGRAM ERROR - * 14 - DATAGRAM QUERY REQUEST - * 15 - DATAGRAM POSITIVE QUERY RESPONSE - * 16 - DATAGRAM NEGATIVE QUERY RESPONSE - * - * Bit definitions of the FLAGS field: - * - * 0 1 2 3 4 5 6 7 - * +---+---+---+---+---+---+---+---+ - * | 0 | 0 | 0 | 0 | SNT | F | M | - * +---+---+---+---+---+---+---+---+ - * - * Symbol Bit(s) Description - * - * M 7 MORE flag, If set then more NetBIOS datagram - * fragments follow. - * - * F 6 FIRST packet flag, If set then this is first - * (and possibly only) fragment of NetBIOS - * datagram - * - * SNT 4,5 Source End-Node type: - * 00 = B node - * 01 = P node - * 10 = M node - * 11 = NBDD - * RESERVED 0-3 Reserved, must be zero (0) - * - * Inputs: - * Nothing - * - * Returns: - * int -> Description - */ - /*ARGSUSED*/ void * -smb_netbios_datagram_service_daemon(void *arg) +smb_netbios_datagram_service(void *arg) { struct sockaddr_in sin; struct datagram *datagram; @@ -999,37 +830,40 @@ (void) mutex_unlock(&smb_dgq_mtx); if ((datagram_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, - "smbd: Could not create AF_INET, SOCK_DGRAM, socket"); - smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1); - return (0); + syslog(LOG_ERR, "nbt datagram: socket failed: %m"); + smb_netbios_event(NETBIOS_EVENT_ERROR); + return (NULL); } + flag = 1; + (void) setsockopt(datagram_sock, SOL_SOCKET, SO_REUSEADDR, &flag, + sizeof (flag)); + bzero(&sin, sizeof (sin)); sin.sin_family = AF_INET; - sin.sin_port = htons(DGM_SRVC_UDP_PORT); + sin.sin_port = htons(IPPORT_NETBIOS_DGM); if (bind(datagram_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) { - syslog(LOG_ERR, "smbd: Bind to name service port %d failed", - DGM_SRVC_UDP_PORT); + syslog(LOG_ERR, "nbt datagram: bind(%d) failed: %m", + IPPORT_NETBIOS_DGM); (void) close(datagram_sock); - smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1); - return (0); + smb_netbios_event(NETBIOS_EVENT_ERROR); + return (NULL); } + + flag = 1; (void) setsockopt(datagram_sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof (flag)); - smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_RUNNING, 1); + smb_netbios_event(NETBIOS_EVENT_DGM_START); - while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) || - (nb_status.state & NETBIOS_BROWSER_RUNNING)) { - if ((datagram = (struct datagram *) - malloc(sizeof (struct datagram))) == 0) { - /* Sleep for 10 sec and try again */ - (void) sleep(10); + while (smb_netbios_running()) { + if ((datagram = malloc(sizeof (struct datagram))) == NULL) { + /* Sleep for 10 seconds and try again */ + smb_netbios_sleep(10); continue; } -ignore: bzero(&datagram->inaddr, sizeof (struct addr_entry)); +ignore: bzero(&datagram->inaddr, sizeof (addr_entry_t)); datagram->inaddr.sinlen = sizeof (datagram->inaddr.sin); datagram->inaddr.forw = datagram->inaddr.back = &datagram->inaddr; @@ -1038,9 +872,8 @@ MAX_DATAGRAM_LENGTH, 0, (struct sockaddr *)&datagram->inaddr.sin, &datagram->inaddr.sinlen)) < 0) { - syslog(LOG_ERR, - "smbd: NETBIOS datagram - recvfrom failed"); - smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_FAILED, 1); + syslog(LOG_ERR, "nbt datagram: recvfrom failed: %m"); + smb_netbios_event(NETBIOS_EVENT_ERROR); break; } @@ -1071,17 +904,12 @@ smb_netbios_BPM_datagram(datagram); } - smb_netbios_chg_status(NETBIOS_DATAGRAM_SVC_RUNNING, 0); - - (void) mutex_lock(&nb_status.mtx); - while (nb_status.state & NETBIOS_BROWSER_RUNNING) - (void) cond_wait(&nb_status.cv, &nb_status.mtx); - (void) mutex_unlock(&nb_status.mtx); + smb_netbios_event(NETBIOS_EVENT_DGM_STOP); + (void) smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP); (void) close(datagram_sock); smb_netbios_datagram_fini(); - smb_tracef("smbd: Netbios Datagram Service is down\n"); - return (0); + return (NULL); } static char diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c Mon Oct 05 11:03:34 2009 -0700 @@ -24,65 +24,42 @@ */ /* - * Description: - * - * Contains base code for netbios name service. - * + * NetBIOS name resolution node types. * - * 6. DEFINED CONSTANTS AND VARIABLES - * - * GENERAL: - * - * SCOPE_ID The name of the NetBIOS scope. + * A B-node (broadcast node) uses broadcasts for name registration + * and resolution. Routers typically do not forward broadcasts and + * only computers on the local subnet will respond. * - * This is expressed as a character - * string meeting the requirements of - * the domain name system and without - * a leading or trailing "dot". + * A P-node (peer-to-peer node) uses a NetBIOS name server (WINS) + * to resolve NetBIOS names, which allows it to work across routers. + * In order to function in a P-node environment, all computers must + * be configured to use the NetBIOS name server because P-nodes do + * not broadcast on the network. * - * An implementation may elect to make - * this a single global value for the - * node or allow it to be specified - * with each separate NetBIOS name - * (thus permitting cross-scope - * references.) - * - * BROADCAST_ADDRESS An IP address composed of the - * nodes's network and subnetwork - * numbers with all remaining bits set - * to one. + * A mixed node (M-node) behaves as a B-node by default. If it cannot + * resolve the name via broadcast then it tries a NetBIOS name server + * lookup (P-node). * - * I.e. "Specific subnet" broadcast - * addressing according to section 2.3 - * of RFC 950. - * - * BCAST_REQ_RETRY_TIMEOUT 250 milliseconds. - * An adaptive timer may be used. + * A hybrid node (H-node) behaves as a P-node by default. If it cannot + * resolve the name using a NetBIOS name server then it resorts to + * broadcasts (B-node). * - * BCAST_REQ_RETRY_COUNT 3 - * - * UCAST_REQ_RETRY_TIMEOUT 5 seconds - * An adaptive timer may be used. - * - * UCAST_REQ_RETRY_COUNT 3 - * - * MAX_DATAGRAM_LENGTH 576 bytes (default) + * NetBIOS Name Service Protocols * - * - * NAME SERVICE: - * - * REFRESH_TIMER Negotiated with NAME for each name. + * A REQUEST packet is always sent to the well known UDP port 137. + * The destination address is normally either the IP broadcast address or + * the address of the NAME - the address of the NAME server it set up at + * initialization time. In rare cases, a request packet will be sent to + * an end node, e.g. a NAME QUERY REQUEST sent to "challenge" a node. * - * CONFLICT_TIMER 1 second - * Implementations may chose a longer - * value. - * + * A RESPONSE packet is always sent to the source UDP port and source IP + * address of the request packet. * - * NAME_SERVICE_TCP_PORT 137 (decimal) + * A DEMAND packet must always be sent to the well known UDP port 137. + * There is no restriction on the target IP address. * - * NAME_SERVICE_UDP_PORT 137 (decimal) - * - * INFINITE_TTL 0 + * A transaction ID is a value composed from the requestor's IP address and + * a unique 16 bit value generated by the originator of the transaction. */ #include @@ -99,54 +76,113 @@ #include #include -#define NAME_HEADER_SIZE 12 +/* + * RFC 1002 4.2.1.1. HEADER + */ +#define QUESTION_TYPE_NETBIOS_GENERAL 0x20 +#define QUESTION_TYPE_NETBIOS_STATUS 0x21 + +#define QUESTION_CLASS_INTERNET 0x0001 + +/* + * RFC 1002 4.2.1.3. RESOURCE RECORD + */ +#define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001 +#define RR_TYPE_NAME_SERVER_RESOURCE 0x0002 +#define RR_TYPE_NULL_RESOURCE 0x000A +#define RR_TYPE_NETBIOS_RESOURCE 0x0020 +#define RR_TYPE_NETBIOS_STATUS 0x0021 + +/* + * + * RESOURCE RECORD RR_CLASS field definitions + */ +#define RR_CLASS_INTERNET_CLASS 0x0001 -typedef struct name_reply { - struct name_reply *forw; - struct name_reply *back; - struct name_packet *packet; - struct addr_entry *addr; - unsigned short name_trn_id; - unsigned short flags; -} name_reply; +/* + * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of NB. + */ +#define RR_FLAGS_NB_ONT_MASK 0x6000 +#define RR_FLAGS_NB_ONT_B_NODE 0x0000 +#define RR_FLAGS_NB_ONT_P_NODE 0x2000 +#define RR_FLAGS_NB_ONT_M_NODE 0x4000 +#define RR_FLAGS_NB_ONT_RESERVED 0x6000 +#define RR_FLAGS_NB_GROUP_NAME 0x8000 -static struct name_reply reply_queue; -static mutex_t rq_mtx; +#define NAME_FLAGS_PERMANENT_NAME 0x0200 +#define NAME_FLAGS_ACTIVE_NAME 0x0400 +#define NAME_FLAGS_CONFLICT 0x0800 +#define NAME_FLAGS_DEREGISTER 0x1000 +#define NAME_FLAGS_ONT_MASK 0x6000 +#define NAME_FLAGS_ONT_B_NODE 0x0000 +#define NAME_FLAGS_ONT_P_NODE 0x2000 +#define NAME_FLAGS_ONT_M_NODE 0x4000 +#define NAME_FLAGS_ONT_RESERVED 0x6000 +#define NAME_FLAGS_GROUP_NAME 0x8000 + +#define MAX_NETBIOS_REPLY_DATA_SIZE 500 + +#define NAME_HEADER_SIZE 12 -static mutex_t reply_mtx; -static cond_t reply_cv; +typedef struct nbt_name_reply { + struct nbt_name_reply *forw; + struct nbt_name_reply *back; + struct name_packet *packet; + addr_entry_t *addr; + uint16_t name_trn_id; + boolean_t reply_ready; +} nbt_name_reply_t; + +static nbt_name_reply_t reply_queue; +static mutex_t rq_mtx; +static cond_t rq_cv; + +static mutex_t nbt_name_config_mtx; static name_queue_t delete_queue; static name_queue_t refresh_queue; -/* - * Flag to control whether or not NetBIOS name refresh requests - * are logged. Set to non-zero to enable logging. - */ - -static unsigned short netbios_name_transcation_id = 1; static int name_sock = 0; static int bcast_num = 0; static int nbns_num = 0; -static struct addr_entry smb_bcast_list[SMB_PI_MAX_NETWORKS]; -static struct addr_entry smb_nbns[SMB_PI_MAX_WINS]; +static addr_entry_t smb_bcast_list[SMB_PI_MAX_NETWORKS]; +static addr_entry_t smb_nbns[SMB_PI_MAX_WINS]; -static int smb_netbios_process_response(unsigned short, struct addr_entry *, +static int smb_netbios_process_response(uint16_t, addr_entry_t *, struct name_packet *, uint32_t); -static int smb_send_name_service_packet(struct addr_entry *addr, +static int smb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet); +/* + * Allocate a transaction id. + */ +static uint16_t +smb_netbios_name_trn_id(void) +{ + static uint16_t trn_id; + static mutex_t trn_id_mtx; + + (void) mutex_lock(&trn_id_mtx); + + do { + ++trn_id; + } while (trn_id == 0 || trn_id == (uint16_t)-1); + + (void) mutex_unlock(&trn_id_mtx); + return (trn_id); +} + static int -smb_end_node_challenge(struct name_reply *reply_info) +smb_end_node_challenge(nbt_name_reply_t *reply_info) { int rc; uint32_t retry; - unsigned short tid; + uint16_t tid; struct resource_record *answer; struct name_question question; - struct addr_entry *addr; + addr_entry_t *addr; struct name_entry *destination; struct name_packet packet; struct timespec st; @@ -176,7 +212,7 @@ addr = &destination->addr_list; for (retry = 0; retry < UCAST_REQ_RETRY_COUNT; retry++) { - tid = netbios_name_transcation_id++; + tid = smb_netbios_name_trn_id(); packet.name_trn_id = tid; if (smb_send_name_service_packet(addr, &packet) >= 0) { if ((rc = smb_netbios_process_response(tid, addr, @@ -191,21 +227,20 @@ return (0); } - -static struct name_reply * -smb_name_get_reply(unsigned short tid, uint32_t timeout) +static nbt_name_reply_t * +smb_name_get_reply(uint16_t tid, uint32_t timeout) { - unsigned short info; + uint16_t info; struct resource_record *answer; - struct name_reply *reply; + nbt_name_reply_t *reply; uint32_t wait_time, to_save; /* in millisecond */ struct timeval wt; timestruc_t to; to_save = timeout; - reply = (struct name_reply *)malloc(sizeof (struct name_reply)); - if (reply != 0) { - reply->flags = 0; + reply = malloc(sizeof (nbt_name_reply_t)); + if (reply != NULL) { + reply->reply_ready = B_FALSE; reply->name_trn_id = tid; (void) mutex_lock(&rq_mtx); QUEUE_INSERT_TAIL(&reply_queue, reply); @@ -215,13 +250,13 @@ (void) gettimeofday(&wt, 0); wait_time = wt.tv_usec / 1000; - (void) mutex_lock(&reply_mtx); to.tv_sec = 0; to.tv_nsec = timeout * 1000000; - (void) cond_reltimedwait(&reply_cv, &reply_mtx, &to); - (void) mutex_unlock(&reply_mtx); + (void) mutex_lock(&rq_mtx); + (void) cond_reltimedwait(&rq_cv, &rq_mtx, &to); + (void) mutex_unlock(&rq_mtx); - if (reply->flags != 0) { + if (reply->reply_ready) { info = reply->packet->info; if (PACKET_TYPE(info) == WACK_RESPONSE) { answer = reply->packet->answer; @@ -231,7 +266,7 @@ free(reply->addr); free(reply->packet); timeout = to_save + wait_time; - reply->flags = 0; + reply->reply_ready = B_FALSE; reply->name_trn_id = tid; (void) mutex_lock(&rq_mtx); QUEUE_INSERT_TAIL(&reply_queue, reply); @@ -257,9 +292,9 @@ } static void -smb_reply_ready(struct name_packet *packet, struct addr_entry *addr) +smb_reply_ready(struct name_packet *packet, addr_entry_t *addr) { - struct name_reply *reply; + nbt_name_reply_t *reply; struct resource_record *answer; (void) mutex_lock(&rq_mtx); @@ -267,16 +302,12 @@ reply = reply->forw) { if (reply->name_trn_id == packet->name_trn_id) { QUEUE_CLIP(reply); - (void) mutex_unlock(&rq_mtx); reply->addr = addr; reply->packet = packet; - - (void) mutex_lock(&reply_mtx); - reply->flags |= 0x0001; /* reply ready */ - (void) cond_signal(&reply_cv); - (void) mutex_unlock(&reply_mtx); - + reply->reply_ready = B_TRUE; + (void) cond_signal(&rq_cv); + (void) mutex_unlock(&rq_mtx); return; } } @@ -292,12 +323,12 @@ } static int -smb_netbios_process_response(unsigned short tid, struct addr_entry *addr, +smb_netbios_process_response(uint16_t tid, addr_entry_t *addr, struct name_packet *packet, uint32_t timeout) { int rc = 0; - unsigned short info; - struct name_reply *reply; + uint16_t info; + nbt_name_reply_t *reply; struct resource_record *answer; struct name_entry *name; struct name_entry *entry; @@ -322,13 +353,16 @@ */ addr->attributes &= ~NAME_ATTR_LOCAL; - addr->refresh_ttl = addr->ttl = - (answer && answer->ttl) ? - (answer->ttl >> 1) : - TO_SECONDS(DEFAULT_TTL); + if (answer->ttl) + addr->ttl = answer->ttl; + else + addr->ttl = DEFAULT_TTL; + addr->refresh_ttl = TO_SECONDS(addr->ttl); + addr->ttl = addr->refresh_ttl; + addr = addr->forw; } while (addr != &answer->name->addr_list); - smb_netbios_name_dump(answer->name); + smb_netbios_name_logf(answer->name); (void) smb_netbios_cache_insert_list(answer->name); rc = 1; } else { @@ -362,7 +396,7 @@ */ entry->attributes |= NAME_ATTR_CONFLICT; syslog(LOG_DEBUG, - "NETBIOS Name conflict: %15.15s", + "nbns: name conflict: %15.15s", entry->name); smb_netbios_cache_unlock_entry(entry); } @@ -377,8 +411,8 @@ * TTL, for this name */ question = packet->question; - ttl = (answer && answer->ttl) ? answer->ttl >> 1 - : TO_SECONDS(DEFAULT_TTL); + ttl = (answer && answer->ttl) ? answer->ttl : DEFAULT_TTL; + ttl = TO_SECONDS(ttl); if ((entry = smb_netbios_cache_lookup(question->name)) != 0) { addr = &entry->addr_list; do { @@ -442,13 +476,11 @@ * -1 -> Hard error, can not possibly encode * -2 -> Need more memory in buf -- it's too small */ - static int -smb_name_buf_from_packet(unsigned char *buf, - int n_buf, +smb_name_buf_from_packet(unsigned char *buf, int n_buf, struct name_packet *npb) { - struct addr_entry *raddr; + addr_entry_t *raddr; unsigned char *heap = buf; unsigned char *end_heap = heap + n_buf; unsigned char *dnptrs[32]; @@ -624,27 +656,15 @@ return (name_len); } - /* * smb_name_buf_to_packet * - * Description: - * Convert the bits and bytes that came from the wire - * into a NetBIOS Name Server Packet Block (npb). - * The "block" is used as a heap. + * Convert the bits and bytes that came from the wire into a NetBIOS + * Name Server Packet Block (npb). The "block" is used as a heap. * - * Inputs: - * char * buf -> Buffer, from the wire - * int n_buf -> Length of 'buf' - * name_packet *npb -> Packet block, decode into - * int n_npb -> Max bytes in 'npb' - * - * Returns: - * >0 -> Decode (parse) successful, value is byte length of npb - * -1 -> Hard error, can not possibly decode - * -2 -> Need more memory in npb -- it's too small + * Returns a pointer to a name packet on success. Otherwise, returns + * a NULL pointer. */ - static struct name_packet * smb_name_buf_to_packet(char *buf, int n_buf) { @@ -655,16 +675,15 @@ char name_buf[MAX_NAME_LENGTH]; struct resource_record *nrr = 0; int rc, i, n, nn, ns; - unsigned short name_trn_id, info; - unsigned short qdcount, ancount, nscount, arcount; - struct addr_entry *next; + uint16_t name_trn_id, info; + uint16_t qdcount, ancount, nscount, arcount; + addr_entry_t *next; int name_len; if (n_buf < NAME_HEADER_SIZE) { /* truncated header */ - syslog(LOG_DEBUG, "SmbNBNS: packet is too short (%d)", - n_buf); - return (0); + syslog(LOG_DEBUG, "nbns: short packet (%d bytes)", n_buf); + return (NULL); } name_trn_id = BE_IN16(scan); scan += 2; @@ -681,11 +700,10 @@ ((unsigned)nscount * (sizeof (struct resource_record) + ns)) + ((unsigned)arcount * (sizeof (struct resource_record) + ns)); - if ((npb = (struct name_packet *)malloc(n)) == 0) { - return (0); - } + if ((npb = malloc(n)) == NULL) + return (NULL); + bzero(npb, n); - heap = npb->block_data; npb->name_trn_id = name_trn_id; npb->info = info; @@ -748,7 +766,7 @@ (char *)scan_end); if (name_len <= 0) { free(npb); - return (0); + return (NULL); } smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0, @@ -758,14 +776,14 @@ if (rc < 0) { /* Couldn't decode the question name */ free(npb); - return (0); + return (NULL); } scan += name_len; if (scan + 4 > scan_end) { /* no room for Question Type(2) and Class(2) fields */ free(npb); - return (0); + return (NULL); } npb->question[i].question_type = BE_IN16(scan); scan += 2; @@ -786,7 +804,7 @@ (char *)scan_end); if (name_len <= 0) { free(npb); - return (0); + return (NULL); } rc = name_len; } @@ -798,7 +816,7 @@ * RDLENGTH (2) fields. */ free(npb); - return (0); + return (NULL); } smb_init_name_struct(NETBIOS_EMPTY_NAME, 0, 0, 0, 0, 0, 0, @@ -806,7 +824,7 @@ if ((rc = smb_first_level_name_decode((unsigned char *)name_buf, nrr[i].name)) < 0) { free(npb); - return (0); + return (NULL); } nrr[i].rr_type = BE_IN16(scan); scan += 2; @@ -818,7 +836,7 @@ if ((scan + n) > scan_end) { /* no room for RDATA */ free(npb); - return (0); + return (NULL); } bcopy(scan, heap, n); @@ -829,13 +847,12 @@ if (nn == 6) next = &nrr[i].name->addr_list; else { - next = (struct addr_entry *) - malloc( - sizeof (struct addr_entry)); + next = malloc( + sizeof (addr_entry_t)); if (next == 0) { /* not enough memory */ free(npb); - return (0); + return (NULL); } QUEUE_INSERT_TAIL( &nrr[i].name->addr_list, @@ -849,7 +866,7 @@ &next->sin.sin_addr.s_addr, scan + 2, sizeof (uint32_t)); next->sin.sin_port = - htons(DGM_SRVC_UDP_PORT); + htons(IPPORT_NETBIOS_DGM); nn -= 6; scan += 6; } @@ -863,7 +880,6 @@ return (npb); } - /* * smb_send_name_service_packet * @@ -879,10 +895,8 @@ * success -> >0 * failure -> <=0 */ - static int -smb_send_name_service_packet(struct addr_entry *addr, - struct name_packet *packet) +smb_send_name_service_packet(addr_entry_t *addr, struct name_packet *packet) { unsigned char buf[MAX_DATAGRAM_LENGTH]; int len; @@ -897,293 +911,6 @@ } /* - * 4.2.1.1. HEADER - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID | OPCODE | NM_FLAGS | RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | QDCOUNT | ANCOUNT | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NSCOUNT | ARCOUNT | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * NAME_TRN_ID Transaction ID for Name Service Transaction. - * Requester places a unique value for each active - * transaction. Responder puts NAME_TRN_ID value - * from request packet in response packet. - * - * OPCODE Packet type code, see table below. - * - * NM_FLAGS Flags for operation, see table below. - * - * RCODE Result codes of request. Table of RCODE values - * for each response packet below. - * - * QDCOUNT Unsigned 16 bit integer specifying the number of - * entries in the question section of a Name - * - * Service packet. Always zero (0) for responses. - * Must be non-zero for all NetBIOS Name requests. - * - * ANCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the answer section of a Name - * Service packet. - * - * NSCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the authority section of a - * Name Service packet. - * - * ARCOUNT Unsigned 16 bit integer specifying the number of - * resource records in the additional records - * section of a Name Service packet. - * - * The OPCODE field is defined as: - * - * 0 1 2 3 4 - * +---+---+---+---+---+ - * | R | OPCODE | - * +---+---+---+---+---+ - * - * Symbol Bit(s) Description - * - * OPCODE 1-4 Operation specifier: - * 0 = query - * 5 = registration - * 6 = release - * 7 = WACK - * 8 = refresh - * - * R 0 RESPONSE flag: - * if bit == 0 then request packet - * if bit == 1 then response packet. - */ - - -/* - * The NM_FLAGS field is defined as: - * - * - * 0 1 2 3 4 5 6 - * +---+---+---+---+---+---+---+ - * |AA |TC |RD |RA | 0 | 0 | B | - * +---+---+---+---+---+---+---+ - * - * Symbol Bit(s) Description - * - * B 6 Broadcast Flag. - * = 1: packet was broadcast or multicast - * = 0: unicast - * - * RA 3 Recursion Available Flag. - * - * Only valid in responses from a NetBIOS Name - * Server -- must be zero in all other - * responses. - * - * If one (1) then the NAME supports recursive - * query, registration, and release. - * - * If zero (0) then the end-node must iterate - * for query and challenge for registration. - * - * RD 2 Recursion Desired Flag. - * - * May only be set on a request to a NetBIOS - * Name Server. - * - * The NAME will copy its state into the - * response packet. - * - * If one (1) the NAME will iterate on the - * query, registration, or release. - * - * TC 1 Truncation Flag. - * - * Set if this message was truncated because the - * datagram carrying it would be greater than - * 576 bytes in length. Use TCP to get the - * information from the NetBIOS Name Server. - * - * AA 0 Authoritative Answer flag. - * - * Must be zero (0) if R flag of OPCODE is zero - * (0). - * - * If R flag is one (1) then if AA is one (1) - * then the node responding is an authority for - * the domain name. - * - * End nodes responding to queries always set - * this bit in responses. - * - */ - -/* - * 4.2.1.2. QUESTION SECTION - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | QUESTION_TYPE | QUESTION_CLASS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * QUESTION_NAME The compressed name representation of the - * NetBIOS name for the request. - * - * QUESTION_TYPE The type of request. The values for this field - * are specified for each request. - * - * QUESTION_CLASS The class of the request. The values for this - * field are specified for each request. - * - * QUESTION_TYPE is defined as: - * - * Symbol Value Description: - * - * NB 0x0020 NetBIOS general Name Service Resource Record - * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE - * STATUS REQUEST) - * - * QUESTION_CLASS is defined as: - * - * Symbol Value Description: - * - * IN 0x0001 Internet class - */ - -#define QUESTION_TYPE_NETBIOS_GENERAL 0x20 -#define QUESTION_TYPE_NETBIOS_STATUS 0x21 - -#define QUESTION_CLASS_INTERNET 0x0001 - -/* - * - * 4.2.1.3. RESOURCE RECORD - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RR_TYPE | RR_CLASS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - * / / - * / RDATA / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Field Description - * - * RR_NAME The compressed name representation of the - * NetBIOS name corresponding to this resource - * record. - * - * RR_TYPE Resource record type code - * - * RR_CLASS Resource record class code - * - * TTL The Time To Live of a the resource record's - * name. - * - * RDLENGTH Unsigned 16 bit integer that specifies the - * number of bytes in the RDATA field. - * - * RDATA RR_CLASS and RR_TYPE dependent field. Contains - * the resource information for the NetBIOS name. - * - * RESOURCE RECORD RR_TYPE field definitions: - * - * Symbol Value Description: - * - * A 0x0001 IP address Resource Record (See REDIRECT NAME - * QUERY RESPONSE) - * NS 0x0002 Name Server Resource Record (See REDIRECT - * NAME QUERY RESPONSE) - * NULL 0x000A NULL Resource Record (See WAIT FOR - * ACKNOWLEDGEMENT RESPONSE) - * NB 0x0020 NetBIOS general Name Service Resource Record - * (See NB_FLAGS and NB_ADDRESS, below) - * NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE - * STATUS RESPONSE) - */ - -#define RR_TYPE_IP_ADDRESS_RESOURCE 0x0001 -#define RR_TYPE_NAME_SERVER_RESOURCE 0x0002 -#define RR_TYPE_NULL_RESOURCE 0x000A -#define RR_TYPE_NETBIOS_RESOURCE 0x0020 -#define RR_TYPE_NETBIOS_STATUS 0x0021 - -/* - * - * RESOURCE RECORD RR_CLASS field definitions: - * - * Symbol Value Description: - * - * IN 0x0001 Internet class - */ -#define RR_CLASS_INTERNET_CLASS 0x0001 - -/* - * - * NB_FLAGS field of the RESOURCE RECORD RDATA field for RR_TYPE of - * "NB": - * - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | G | ONT | RESERVED | - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * - * Symbol Bit(s) Description: - * - * RESERVED 3-15 Reserved for future use. Must be zero (0). - * ONT 1,2 Owner Node Type: - * 00 = B node - * 01 = P node - * 10 = M node - * 11 = Reserved for future use - * For registration requests this is the - * claimant's type. - * For responses this is the actual owner's - * type. - * - * G 0 Group Name Flag. - * If one (1) then the RR_NAME is a GROUP - * NetBIOS name. - * If zero (0) then the RR_NAME is a UNIQUE - * NetBIOS name. - * - * The NB_ADDRESS field of the RESOURCE RECORD RDATA field for - * RR_TYPE of "NB" is the IP address of the name's owner. - * - */ -#define RR_FLAGS_NB_ONT_MASK 0x6000 -#define RR_FLAGS_NB_ONT_B_NODE 0x0000 -#define RR_FLAGS_NB_ONT_P_NODE 0x2000 -#define RR_FLAGS_NB_ONT_M_NODE 0x4000 -#define RR_FLAGS_NB_ONT_RESERVED 0x6000 - -#define RR_FLAGS_NB_GROUP_NAME 0x8000 - -/* * smb_netbios_send_rcv * * This function sends the given NetBIOS packet to the given @@ -1195,12 +922,11 @@ * 1 Got reply */ static int -smb_netbios_send_rcv(int bcast, struct addr_entry *destination, - struct name_packet *packet, - uint32_t retries, uint32_t timeout) +smb_netbios_send_rcv(int bcast, addr_entry_t *destination, + struct name_packet *packet, uint32_t retries, uint32_t timeout) { uint32_t retry; - unsigned short tid; + uint16_t tid; struct timespec st; int rc; @@ -1208,7 +934,7 @@ if ((destination->flags & ADDR_FLAG_VALID) == 0) return (0); - tid = netbios_name_transcation_id++; + tid = smb_netbios_name_trn_id(); packet->name_trn_id = tid; if (smb_send_name_service_packet(destination, packet) >= 0) { rc = smb_netbios_process_response(tid, destination, @@ -1230,45 +956,7 @@ } /* - * 4.2.2. NAME REGISTRATION REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x5 |0|0|1|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Since the RR_NAME is the same name as the QUESTION_NAME, the - * RR_NAME representation must use pointers to the QUESTION_NAME - * name's labels to guarantee the length of the datagram is less - * than the maximum 576 bytes. See section above on name formats - * and also page 31 and 32 of RFC 883, Domain Names - Implementation - * and Specification, for a complete description of compressed name - * label pointers. + * RFC 1002 4.2.2. NAME REGISTRATION REQUEST */ static int smb_send_name_registration_request(int bcast, struct name_question *question, @@ -1277,15 +965,15 @@ int gotreply = 0; uint32_t retries; uint32_t timeout; - struct addr_entry *destination; + addr_entry_t *destination; struct name_packet packet; unsigned char type; int i, addr_num, rc; type = question->name->name[15]; - if ((type != 0x00) && (type != 0x20)) { - syslog(LOG_ERR, "netbios: error trying to register" - " non-local name"); + if ((type != NBT_WKSTA) && (type != NBT_SERVER)) { + syslog(LOG_DEBUG, "nbns: name registration bad type (0x%02x)", + type); smb_netbios_name_logf(question->name); question->name->attributes &= ~NAME_ATTR_LOCAL; return (-1); @@ -1340,38 +1028,7 @@ } /* - * - * 4.2.4. NAME REFRESH REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x8 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * RFC 1002 4.2.4. NAME REFRESH REQUEST */ /*ARGSUSED*/ static int @@ -1382,15 +1039,15 @@ int gotreply = 0; uint32_t retries; uint32_t timeout; - struct addr_entry *addr; - struct addr_entry *destination; + addr_entry_t *addr; + addr_entry_t *destination; struct name_packet packet; unsigned char type; int i, addr_num, q_addrs = 0; type = question->name->name[15]; - if ((type != 0x00) && (type != 0x20)) { - syslog(LOG_ERR, "attempt to refresh non-local name"); + if ((type != NBT_WKSTA) && (type != NBT_SERVER)) { + syslog(LOG_DEBUG, "nbns: name refresh bad type (0x%02x)", type); smb_netbios_name_logf(question->name); question->name->attributes &= ~NAME_ATTR_LOCAL; return (-1); @@ -1471,78 +1128,12 @@ } /* - * 4.2.5. POSITIVE NAME REGISTRATION RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * - * - * 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x5 |1|0|1|1|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description: - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * SRV_ERR 0x2 Server failure. Problem with NAME, cannot - * process name. - * IMP_ERR 0x4 Unsupported request error. Allowable only - * for challenging NAME when gets an Update type - * registration request. - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not register this name from this host. - * ACT_ERR 0x6 Active error. Name is owned by another node. - * CFT_ERR 0x7 Name in conflict error. A UNIQUE name is - * owned by more than one node. + * RFC 1002 4.2.5. POSITIVE NAME REGISTRATION RESPONSE + * RFC 1002 4.2.6. NEGATIVE NAME REGISTRATION RESPONSE */ static int -smb_send_name_registration_response(struct addr_entry *addr, - struct name_packet *original_packet, unsigned short rcode) +smb_send_name_registration_response(addr_entry_t *addr, + struct name_packet *original_packet, uint16_t rcode) { struct name_packet packet; struct resource_record answer; @@ -1573,43 +1164,7 @@ } /* - * 4.2.9. NAME RELEASE REQUEST & DEMAND - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x6 |0|0|0|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Since the RR_NAME is the same name as the QUESTION_NAME, the - * RR_NAME representation must use label string pointers to the - * QUESTION_NAME labels to guarantee the length of the datagram is - * less than the maximum 576 bytes. This is the same condition as - * with the NAME REGISTRATION REQUEST. + * RFC 1002 4.2.9. NAME RELEASE REQUEST & DEMAND */ static int smb_send_name_release_request_and_demand(int bcast, @@ -1620,7 +1175,7 @@ int addr_num; uint32_t retries; uint32_t timeout; - struct addr_entry *destination; + addr_entry_t *destination; struct name_packet packet; if (bcast == BROADCAST) { @@ -1661,81 +1216,13 @@ } /* - * 4.2.10. POSITIVE NAME RELEASE RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * - * 4.2.11. NEGATIVE NAME RELEASE RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x6 |1|0|0|0|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0006 | NB_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description: - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * - * SRV_ERR 0x2 Server failure. Problem with NAME, cannot - * process name. - * - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not release this name from this host. - * - * ACT_ERR 0x6 Active error. Name is owned by another node. - * Only that node may release it. A NetBIOS - * Name Server can optionally allow a node to - * release a name it does not own. This would - * facilitate detection of inactive names for - * nodes that went down silently. + * RFC 1002 4.2.10. POSITIVE NAME RELEASE RESPONSE + * RFC 1002 4.2.11. NEGATIVE NAME RELEASE RESPONSE */ static int /* LINTED - E_STATIC_UNUSED */ -smb_send_name_release_response(struct addr_entry *addr, - struct name_packet *original_packet, unsigned short rcode) +smb_send_name_release_response(addr_entry_t *addr, + struct name_packet *original_packet, uint16_t rcode) { struct name_packet packet; struct resource_record answer; @@ -1765,25 +1252,7 @@ } /* - * - * 4.2.12. NAME QUERY REQUEST - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0001 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / QUESTION_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * RFC 1002 4.2.12. NAME QUERY REQUEST */ static int smb_send_name_query_request(int bcast, struct name_question *question) @@ -1791,8 +1260,8 @@ int rc = 0; uint32_t retry, retries; uint32_t timeout; - unsigned short tid; - struct addr_entry *destination; + uint16_t tid; + addr_entry_t *destination; struct name_packet packet; int i, addr_num; struct timespec st; @@ -1825,9 +1294,9 @@ for (i = 0; i < addr_num; i++) { for (retry = 0; retry < retries; retry++) { - if ((destination->flags & ADDR_FLAG_VALID) == 0) + if ((destination[i].flags & ADDR_FLAG_VALID) == 0) break; - tid = netbios_name_transcation_id++; + tid = smb_netbios_name_trn_id(); packet.name_trn_id = tid; if (smb_send_name_service_packet(&destination[i], @@ -1846,101 +1315,19 @@ return (rc); } - /* - * - * 4.2.13. POSITIVE NAME QUERY RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|T|1|?|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB (0x0020) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | TTL | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - * | | - * / ADDR_ENTRY ARRAY / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The ADDR_ENTRY ARRAY a sequence of zero or more ADDR_ENTRY - * records. Each ADDR_ENTRY record represents an owner of a name. - * For group names there may be multiple entries. However, the list - * may be incomplete due to packet size limitations. Bit 22, "T", - * will be set to indicate truncated data. - * - * Each ADDR_ENTRY has the following format: - * - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_FLAGS | NB_ADDRESS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NB_ADDRESS (continued) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * - * - * 4.2.14. NEGATIVE NAME QUERY RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|0|1|?|0 0|0| RCODE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * / / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NULL (0x000A) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * RCODE field values: - * - * Symbol Value Description - * - * FMT_ERR 0x1 Format Error. Request was invalidly - * formatted. - * SRV_ERR 0x2 Server failure. Problem with NAME, cannot - * process name. - * NAM_ERR 0x3 Name Error. The name requested does not - * exist. - * IMP_ERR 0x4 Unsupported request error. Allowable only - * for challenging NAME when gets an Update type - * registration request. - * RFS_ERR 0x5 Refused error. For policy reasons server - * will not register this name from this host. + * RFC 1002 4.2.13. POSITIVE NAME QUERY RESPONSE + * RFC 1002 4.2.14. NEGATIVE NAME QUERY RESPONSE */ static int -smb_send_name_query_response(struct addr_entry *addr, +smb_send_name_query_response(addr_entry_t *addr, struct name_packet *original_packet, struct name_entry *entry, - unsigned short rcode) + uint16_t rcode) { - struct addr_entry *raddr; + addr_entry_t *raddr; struct name_packet packet; struct resource_record answer; - unsigned short attr; + uint16_t attr; unsigned char data[MAX_DATAGRAM_LENGTH]; unsigned char *scan = data; uint32_t ret_addr; @@ -1989,141 +1376,10 @@ } /* - * 4.2.18. NODE STATUS RESPONSE - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0001 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x0000 | 0x0000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * / RR_NAME / - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NBSTAT (0x0021) | IN (0x0001) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x00000000 | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | RDLENGTH | NUM_NAMES | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + - * | | - * + + - * / NODE_NAME ARRAY / - * + + - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * + + - * / STATISTICS / - * + + - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries - * of NODE_NAME records. Each NODE_NAME entry represents an active - * name in the same NetBIOS scope as the requesting name in the - * local name table of the responder. RR_NAME is the requesting - * name. - * - * NODE_NAME Entry: - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | - * +--- ---+ - * | | - * +--- NETBIOS FORMAT NAME ---+ - * | | - * +--- ---+ - * | | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NAME_FLAGS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * The NAME_FLAGS field: - * - * 1 1 1 1 1 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * | G | ONT |DRG|CNF|ACT|PRM| RESERVED | - * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - * - * The NAME_FLAGS field is defined as: - * - * Symbol Bit(s) Description: - * - * RESERVED 7-15 Reserved for future use. Must be zero (0). - * PRM 6 Permanent Name Flag. If one (1) then entry - * is for the permanent node name. Flag is zero - * (0) for all other names. - * ACT 5 Active Name Flag. All entries have this flag - * set to one (1). - * CNF 4 Conflict Flag. If one (1) then name on this - * node is in conflict. - * DRG 3 Deregister Flag. If one (1) then this name - * is in the process of being deleted. - * ONT 1,2 Owner Node Type: - * 00 = B node - * 01 = P node - * 10 = M node - * 11 = Reserved for future use - * G 0 Group Name Flag. - * If one (1) then the name is a GROUP NetBIOS - * name. - * If zero (0) then it is a UNIQUE NetBIOS name. + * RFC 1002 4.2.18. NODE STATUS RESPONSE */ -#define NAME_FLAGS_PERMANENT_NAME 0x0200 -#define NAME_FLAGS_ACTIVE_NAME 0x0400 -#define NAME_FLAGS_CONFLICT 0x0800 -#define NAME_FLAGS_DEREGISTER 0x1000 -#define NAME_FLAGS_ONT_MASK 0x6000 -#define NAME_FLAGS_ONT_B_NODE 0x0000 -#define NAME_FLAGS_ONT_P_NODE 0x2000 -#define NAME_FLAGS_ONT_M_NODE 0x4000 -#define NAME_FLAGS_ONT_RESERVED 0x6000 -#define NAME_FLAGS_GROUP_NAME 0x8000 - - -/* - * STATISTICS Field of the NODE STATUS RESPONSE: - * - * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | UNIT_ID (Unique unit ID) | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | UNIT_ID,continued | JUMPERS | TEST_RESULT | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | VERSION_NUMBER | PERIOD_OF_STATISTICS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_OF_CRCs | NUMBER_ALIGNMENT_ERRORS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_OF_COLLISIONS | NUMBER_SEND_ABORTS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_GOOD_SENDS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_GOOD_RECEIVES | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_RETRANSMITS | NUMBER_NO_RESOURCE_CONDITIONS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | NUMBER_FREE_COMMAND_BLOCKS | TOTAL_NUMBER_COMMAND_BLOCKS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |MAX_TOTAL_NUMBER_COMMAND_BLOCKS| NUMBER_PENDING_SESSIONS | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | MAX_NUMBER_PENDING_SESSIONS | MAX_TOTAL_SESSIONS_POSSIBLE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | SESSION_DATA_PACKET_SIZE | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ -#define MAX_NETBIOS_REPLY_DATA_SIZE 500 - static int -smb_send_node_status_response(struct addr_entry *addr, +smb_send_node_status_response(addr_entry_t *addr, struct name_packet *original_packet) { uint32_t net_ipaddr; @@ -2265,152 +1521,14 @@ return (smb_send_name_service_packet(addr, &packet)); } -/* - * - * 5.1. NAME SERVICE PROTOCOLS - * - * A REQUEST packet is always sent to the well known UDP port - - * NAME_SERVICE_UDP_PORT. The destination address is normally - * either the IP broadcast address or the address of the NAME - the - * address of the NAME server it set up at initialization time. In - * rare cases, a request packet will be sent to an end node, e.g. a - * NAME QUERY REQUEST sent to "challenge" a node. - * - * A RESPONSE packet is always sent to the source UDP port and - * source IP address of the request packet. - * - * A DEMAND packet must always be sent to the well known UDP port - - * NAME_SERVICE_UDP_PORT. There is no restriction on the target IP - * address. - * - * Terms used in this section: - * - * tid - Transaction ID. This is a value composed from - * the requestor's IP address and a unique 16 bit - * value generated by the originator of the - * transaction. - */ - - -/* - * - * 5.1.1. B-NODE ACTIVITY - * - * 5.1.1.1. B-NODE ADD NAME - * - * PROCEDURE add_name(name) - * - * (* - * * Host initiated processing for a B node - * *) - * BEGIN - * - * REPEAT - * - * (* build name service packet *) - * - * ONT = B_NODE; (* broadcast node *) - * G = UNIQUE; (* unique name *) - * TTL = 0; - * - * broadcast NAME REGISTRATION REQUEST packet; - * - * (* - * * remote node(s) will send response packet - * * if applicable - * *) - * pause(BCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * - * IF no response packet was received THEN - * BEGIN (* no response *) - * (* - * * Build packet - * *) - * - * ONT = B_NODE; (* broadcast node *) - * G = UNIQUE; (* unique name *) - * TTL = 0; - * - * (* - * * Let other nodes known you have the name - * *) - * - * broadcast NAME UPDATE REQUEST packet; - * (* name can be added to local name table *) - * return success; - * END (* no response *) - * ELSE - * BEGIN (* got response *) - * - * (* - * * Match return transaction id - * * against tid sent in request - * *) - * - * IF NOT response tid = request tid THEN - * BEGIN - * ignore response packet; - * END - * ELSE - * CASE packet type OF - * - * NEGATIVE NAME REGISTRATION RESPONSE: - * - * return failure; (* name cannot be added *) - * - * POSITIVE NAME REGISTRATION RESPONSE: - * END-NODE CHALLENGE NAME REGISTRATION RESPONSE: - * - * (* - * * B nodes should normally not get this - * * response. - * *) - * - * ignore packet; - * END (* case *); - * END (* got response *) - * END (* procedure *) - * - * - * - * 5.1.1.2. B-NODE ADD_GROUP NAME - * - * PROCEDURE add_group_name(name) - * - * (* - * * Host initiated processing for a B node - * *) - * - * BEGIN - * (* - * * same as for a unique name with the - * * exception that the group bit (G) must - * * be set in the request packets. - * *) - * - * ... - * G = GROUP; - * ... - * ... - * - * (* - * * broadcast request ... - * *) - * - * - * END - */ static int smb_name_Bnode_add_name(struct name_entry *name) { struct name_question question; struct resource_record additional; unsigned char data[8]; - unsigned short attr; - struct addr_entry *addr; + uint16_t attr; + addr_entry_t *addr; int rc = 0; addr = &name->addr_list; @@ -2447,68 +1565,6 @@ return (rc); } -/* - * 5.1.1.3. B-NODE FIND_NAME - * - * PROCEDURE find_name(name) - * - * (* - * * Host initiated processing for a B node - * *) - * - * BEGIN - * - * REPEAT - * (* - * * build packet - * *) - * ONT = B; - * TTL = 0; - * G = DONT CARE; - * raddr = raddr->forw; - * - * broadcast NAME QUERY REQUEST packet; - * (* - * * a node might send response packet - * *) - * - * pause(BCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet received OR - * max transmit threshold exceeded - * - * IF no response packet received THEN - * return failure; - * ELSE - * IF NOT response tid = request tid THEN - * ignore packet; - * ELSE - * CASE packet type OF - * POSITIVE NAME QUERY RESPONSE: - * (* - * * Start a timer to detect conflict. - * * - * * Be prepared to detect conflict if - * * any more response packets are received. - * * - * *) - * - * save response as authoritative response; - * start_timer(CONFLICT_TIMER); - * return success; - * - * NEGATIVE NAME QUERY RESPONSE: - * REDIRECT NAME QUERY RESPONSE: - * - * (* - * * B Node should normally not get either - * * response. - * *) - * - * ignore response packet; - * - * END (* case *) - * END (* procedure *) - */ static int smb_name_Bnode_find_name(struct name_entry *name) { @@ -2521,42 +1577,14 @@ return (smb_send_name_query_request(BROADCAST, &question)); } -/* - * 5.1.1.4. B NODE NAME RELEASE - * - * PROCEDURE delete_name (name) - * BEGIN - * - * REPEAT - * - * (* - * * build packet - * *) - * ... - * - * (* - * * send request - * *) - * - * broadcast NAME RELEASE REQUEST packet; - * - * (* - * * no response packet expected - * *) - * - * pause(BCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL retransmit count has been exceeded - * END (* procedure *) - */ static int smb_name_Bnode_delete_name(struct name_entry *name) { struct name_question question; struct resource_record additional; - struct addr_entry *raddr; - unsigned char data[MAX_DATAGRAM_LENGTH]; - unsigned char *scan = data; + addr_entry_t *raddr; + unsigned char data[MAX_DATAGRAM_LENGTH]; + unsigned char *scan = data; uint32_t attr; uint32_t ret_addr; @@ -2591,212 +1619,14 @@ &question, &additional)); } -/* - * - * 5.1.2. P-NODE ACTIVITY - * - * All packets sent or received by P nodes are unicast UDP packets. - * A P node sends name service requests to the NAME node that is - * specified in the P-node configuration. - * - * 5.1.2.1. P-NODE ADD_NAME - * - * PROCEDURE add_name(name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * - * REPEAT - * (* - * * build packet - * *) - * - * ONT = P; - * G = UNIQUE; - * ... - * - * (* - * * send request - * *) - * - * unicast NAME REGISTRATION REQUEST packet; - * - * (* - * * NAME will send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet is received OR - * retransmit count has been exceeded - * - * IF no response packet was received THEN - * BEGIN (* no response *) - * (* - * * NAME is down. Cannot claim name. - * *) - * - * return failure; (* name cannot be claimed *) - * END (* no response *) - * ELSE - * BEGIN (* response *) - * IF NOT response tid = request tid THEN - * BEGIN - * (* Packet may belong to another transaction *) - * ignore response packet; - * END - * ELSE - * CASE packet type OF - * - * POSITIVE NAME REGISTRATION RESPONSE: - * - * (* - * * name can be added - * *) - * - * adjust refresh timeout value, TTL, for this name; - * return success; (* name can be added *) - * - * NEGATIVE NAME REGISTRATION RESPONSE: - * return failure; (* name cannot be added *) - * - * END-NODE CHALLENGE REGISTRATION REQUEST: - * BEGIN (* end node challenge *) - * - * (* - * * The response packet has in it the - * * address of the presumed owner of the - * * name. Challenge that owner. - * * If owner either does not - * * respond or indicates that he no longer - * * owns the name, claim the name. - * * Otherwise, the name cannot be claimed. - * * - * *) - * - * REPEAT - * (* - * * build packet - * *) - * ... - * - * unicast NAME QUERY REQUEST packet to the - * address contained in the END NODE - * CHALLENGE RESPONSE packet; - * - * (* - * * remote node may send response packet - * *) - * - * pause(UCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * IF no response packet is received OR - * NEGATIVE NAME QUERY RESPONSE packet - * received THEN - * BEGIN (* update *) - * - * (* - * * name can be claimed - * *) - * - * REPEAT - * - * (* - * * build packet - * *) - * ... - * - * unicast NAME UPDATE REQUEST to NAME; - * - * (* - * * NAME node will send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet is received or - * retransmit count has been exceeded - * IF no response packet received THEN - * BEGIN (* no response *) - * - * (* - * * name could not be claimed - * *) - * - * return failure; - * END (* no response *) - * ELSE - * CASE packet type OF - * POSITIVE NAME REGISTRATION RESPONSE: - * (* - * * add name - * *) - * return success; - * NEGATIVE NAME REGISTRATION RESPONSE: - * - * (* - * * you lose ... - * *) - * return failure; - * END (* case *) - * END (* update *) - * ELSE - * - * (* - * * received a positive response to the "challenge" - * * Remote node still has name - * *) - * - * return failure; - * END (* end node challenge *) - * END (* response *) - * END (* procedure *) - * - * - * 5.1.2.2. P-NODE ADD GROUP NAME - * - * PROCEDURE add_group_name(name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * (* - * * same as for a unique name, except that the - * * request packet must indicate that a - * * group name claim is being made. - * *) - * - * ... - * G = GROUP; - * ... - * - * (* - * * send packet - * *) - * ... - * - * - * END - */ static int smb_name_Pnode_add_name(struct name_entry *name) { struct name_question question; struct resource_record additional; unsigned char data[8]; - unsigned short attr; - struct addr_entry *addr; + uint16_t attr; + addr_entry_t *addr; int rc = 0; /* build packet */ @@ -2835,8 +1665,8 @@ struct name_question question; struct resource_record additional; unsigned char data[8]; - unsigned short attr; - struct addr_entry *addr; + uint16_t attr; + addr_entry_t *addr; int rc = 0; /* build packet */ @@ -2868,63 +1698,6 @@ return (rc); } -/* - * 5.1.2.3. P-NODE FIND NAME - * - * PROCEDURE find_name(name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * REPEAT - * (* - * * build packet - * *) - * - * ONT = P; - * G = DONT CARE; - * - * unicast NAME QUERY REQUEST packet; - * - * (* - * * a NAME node might send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet received OR - * max transmit threshold exceeded - * - * IF no response packet received THEN - * return failure; - * ELSE - * IF NOT response tid = request tid THEN - * ignore packet; - * ELSE - * CASE packet type OF - * POSITIVE NAME QUERY RESPONSE: - * return success; - * - * REDIRECT NAME QUERY RESPONSE: - * - * (* - * * NAME node wants this end node - * * to use some other NAME node - * * to resolve the query. - * *) - * - * repeat query with NAME address - * in the response packet; - * NEGATIVE NAME QUERY RESPONSE: - * return failure; - * - * END (* case *) - * END (* procedure *) - */ static int smb_name_Pnode_find_name(struct name_entry *name) { @@ -2941,59 +1714,14 @@ return (smb_send_name_query_request(UNICAST, &question)); } -/* - * 5.1.2.4. P-NODE DELETE_NAME - * - * PROCEDURE delete_name (name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * - * REPEAT - * - * (* - * * build packet - * *) - * ... - * - * (* - * * send request - * *) - * - * unicast NAME RELEASE REQUEST packet; - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL retransmit count has been exceeded - * or response been received - * - * IF response has been received THEN - * CASE packet type OF - * POSITIVE NAME RELEASE RESPONSE: - * return success; - * NEGATIVE NAME RELEASE RESPONSE: - * - * (* - * * NAME does want node to delete this - * * name !!! - * *) - * - * return failure; - * END (* case *) - * END (* procedure *) - */ static int smb_name_Pnode_delete_name(struct name_entry *name) { struct name_question question; struct resource_record additional; - struct addr_entry *raddr; - unsigned char data[MAX_DATAGRAM_LENGTH]; - unsigned char *scan = data; + addr_entry_t *raddr; + unsigned char data[MAX_DATAGRAM_LENGTH]; + unsigned char *scan = data; uint32_t attr; uint32_t ret_addr; @@ -3031,254 +1759,6 @@ return (1); } -/* - * 5.1.3. M-NODE ACTIVITY - * - * M nodes behavior is similar to that of P nodes with the addition - * of some B node-like broadcast actions. M node name service - * proceeds in two steps: - * - * 1.Use broadcast UDP based name service. Depending on the - * operation, goto step 2. - * - * 2.Use directed UDP name service. - * - * The following code for M nodes is exactly the same as for a P - * node, with the exception that broadcast operations are done - * before P type operation is attempted. - * - * 5.1.3.1. M-NODE ADD NAME - * - * PROCEDURE add_name(name) - * - * (* - * * Host initiated processing for a M node - * *) - * - * BEGIN - * - * (* - * * check if name exists on the - * * broadcast area - * *) - * REPEAT - * (* build packet *) - * - * .... - * broadcast NAME REGISTRATION REQUEST packet; - * pause(BCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * - * IF valid response received THEN - * BEGIN - * (* cannot claim name *) - * - * return failure; - * END - * - * (* - * * No objections received within the - * * broadcast area. - * * Send request to name server. - * *) - * - * REPEAT - * (* - * * build packet - * *) - * - * ONT = M; - * ... - * - * unicast NAME REGISTRATION REQUEST packet; - * - * (* - * * remote NAME will send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * - * IF no response packet was received THEN - * BEGIN (* no response *) - * (* - * * NAME is down. Cannot claim name. - * *) - * return failure; (* name cannot be claimed *) - * END (* no response *) - * ELSE - * BEGIN (* response *) - * IF NOT response tid = request tid THEN - * BEGIN - * ignore response packet; - * END - * ELSE - * CASE packet type OF - * POSITIVE NAME REGISTRATION RESPONSE: - * - * (* - * * name can be added - * *) - * - * adjust refresh timeout value, TTL; - * return success; (* name can be added *) - * - * NEGATIVE NAME REGISTRATION RESPONSE: - * return failure; (* name cannot be added *) - * - * END-NODE CHALLENGE REGISTRATION REQUEST: - * BEGIN (* end node challenge *) - * - * (* - * * The response packet has in it the - * * address of the presumed owner of the - * * name. Challenge that owner. - * * If owner either does not - * * respond or indicates that he no longer - * * owns the name, claim the name. - * * Otherwise, the name cannot be claimed. - * * - * *) - * - * REPEAT - * (* - * * build packet - * *) - * ... - * - * (* - * * send packet to address contained in the - * * response packet - * *) - * - * unicast NAME QUERY REQUEST packet; - * - * (* - * * remote node may send response packet - * *) - * - * pause(UCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * IF no response packet is received THEN - * BEGIN (* no response *) - * - * (* - * * name can be claimed - * *) - * REPEAT - * - * (* - * * build packet - * *) - * ... - * - * unicast NAME UPDATE REQUEST to NAME; - * - * (* - * * NAME node will send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * - * UNTIL response packet is received or - * retransmit count has been exceeded - * IF no response packet received THEN - * BEGIN (* no response *) - * - * (* - * * name could not be claimed - * *) - * - * return failure; - * END (* no response *) - * ELSE - * CASE packet type OF - * POSITIVE NAME REGISTRATION RESPONSE: - * (* - * * add name - * *) - * - * return success; - * NEGATIVE NAME REGISTRATION RESPONSE: - * (* - * * you lose ... - * *) - * - * return failure; - * END (* case *) - * END (* no response *) - * ELSE - * IF NOT response tid = request tid THEN - * BEGIN - * ignore response packet; - * END - * - * (* - * * received a response to the "challenge" - * * packet - * *) - * - * CASE packet type OF - * POSITIVE NAME QUERY: - * - * (* - * * remote node still has name. - * *) - * - * return failure; - * NEGATIVE NAME QUERY: - * - * (* - * * remote node no longer has name - * *) - * - * return success; - * END (* case *) - * END (* end node challenge *) - * END (* case *) - * END (* response *) - * END (* procedure *) - * - * - * 5.1.3.2. M-NODE ADD GROUP NAME - * - * PROCEDURE add_group_name(name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * (* - * * same as for a unique name, except that the - * * request packet must indicate that a - * * group name claim is being made. - * *) - * - * ... - * G = GROUP; - * ... - * - * (* - * * send packet - * *) - * ... - * - * - * END - */ static int smb_name_Mnode_add_name(struct name_entry *name) { @@ -3302,89 +1782,6 @@ return (smb_name_Bnode_add_name(name)); } -/* - * 5.1.3.3. M-NODE FIND NAME - * - * PROCEDURE find_name(name) - * - * (* - * * Host initiated processing for a M node - * *) - * - * BEGIN - * (* - * * check if any node on the broadcast - * * area has the name - * *) - * - * REPEAT - * (* build packet *) - * ... - * - * broadcast NAME QUERY REQUEST packet; - * pause(BCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet received OR - * max transmit threshold exceeded - * - * IF valid response received THEN - * BEGIN - * save response as authoritative response; - * start_timer(CONFLICT_TIMER); - * return success; - * END - * - * (* - * * no valid response on the b'cast segment. - * * Try the name server. - * *) - * - * REPEAT - * (* - * * build packet - * *) - * - * ONT = M; - * G = DONT CARE; - * - * unicast NAME QUERY REQUEST packet to NAME; - * - * (* - * * a NAME node might send response packet - * *) - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response packet received OR - * max transmit threshold exceeded - * - * IF no response packet received THEN - * return failure; - * ELSE - * IF NOT response tid = request tid THEN - * ignore packet; - * ELSE - * CASE packet type OF - * POSITIVE NAME QUERY RESPONSE: - * return success; - * - * REDIRECT NAME QUERY RESPONSE: - * - * (* - * * NAME node wants this end node - * * to use some other NAME node - * * to resolve the query. - * *) - * - * repeat query with NAME address - * in the response packet; - * NEGATIVE NAME QUERY RESPONSE: - * return failure; - * - * END (* case *) - * END (* procedure *) - */ static int smb_name_Mnode_find_name(struct name_entry *name) { @@ -3407,68 +1804,6 @@ return (smb_name_Bnode_find_name(name)); } -/* - * 5.1.3.4. M-NODE DELETE NAME - * - * PROCEDURE delete_name (name) - * - * (* - * * Host initiated processing for a P node - * *) - * - * BEGIN - * (* - * * First, delete name on NAME - * *) - * - * REPEAT - * - * (* - * * build packet - * struct addr_entry *addr; - * *) - * ... - * - * (* - * * send request - * *) - * - * unicast NAME RELEASE REQUEST packet to NAME; - * - * IF receive a WACK RESPONSE THEN - * pause(time from TTL field of response); - * ELSE - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL retransmit count has been exceeded - * or response been received - * - * IF response has been received THEN - * CASE packet type OF - * POSITIVE NAME RELEASE RESPONSE: - * (* - * * Deletion of name on b'cast segment is deferred - * * until after NAME has deleted the name - * *) - * - * REPEAT - * (* build packet *) - * - * ... - * broadcast NAME RELEASE REQUEST; - * pause(BCAST_REQ_RETRY_TIMEOUT); - * UNTIL rexmt threshold exceeded - * - * return success; - * NEGATIVE NAME RELEASE RESPONSE: - * - * (* - * * NAME does want node to delete this - * * name - * *) - * return failure; - * END (* case *) - * END (* procedure *) - */ static int smb_name_Mnode_delete_name(struct name_entry *name) { @@ -3493,146 +1828,8 @@ return (smb_name_Bnode_delete_name(name)); } -/* - * 5.1.1.5. B-NODE INCOMING PACKET PROCESSING - * - * Following processing is done when broadcast or unicast packets - * are received at the NAME_SERVICE_UDP_PORT. - * - * PROCEDURE process_incoming_packet(packet) - * - * (* - * * Processing initiated by incoming packets for a B node - * *) - * - * BEGIN - * (* - * * Note: response packets are always sent - * * to: - * * source IP address of request packet - * * source UDP port of request packet - * *) - * - * CASE packet type OF - * - * NAME REGISTRATION REQUEST (UNIQUE): - * IF name exists in local name table THEN - * send NEGATIVE_NAME_REGISTRATION_RESPONSE ; - * NAME REGISTRATION REQUEST (GROUP): - * IF name exists in local name table THEN - * BEGIN - * IF local entry is a unique name THEN - * send NEGATIVE_NAME_REGISTRATION_RESPONSE ; - * END - * NAME QUERY REQUEST: - * IF name exists in local name table THEN - * BEGIN - * build response packet; - * send POSITIVE_NAME_QUERY_RESPONSE; - * POSITIVE NAME QUERY RESPONSE: - * IF name conflict timer is not active THEN - * BEGIN - * (* - * * timer has expired already... ignore this - * * packet - * *) - * - * return; - * END - * ELSE (* timer is active *) - * IF a response for this name has previously been - * received THEN - * BEGIN (* existing entry *) - * - * (* - * * we sent out a request packet, and - * * have already received (at least) - * * one response - * * - * * Check if conflict exists. - * * If so, send out a conflict packet. - * * - * * Note: detecting conflict does NOT - * * affect any existing sessions. - * * - * *) - * - * (* - * * Check for name conflict. - * * See "Name Conflict" in Concepts and Methods - * *) - * check saved authoritative response against - * information in this response packet; - * IF conflict detected THEN - * BEGIN - * unicast NAME CONFLICT DEMAND packet; - * IF entry exists in cache THEN - * BEGIN - * remove entry from cache; - * END - * END - * END (* existing entry *) - * ELSE - * BEGIN - * (* - * * Note: If this was the first response - * * to a name query, it would have been - * * handled in the - * * find_name() procedure. - * *) - * - * ignore packet; - * END - * NAME CONFLICT DEMAND: - * IF name exists in local name table THEN - * BEGIN - * mark name as conflict detected; - * - * (* - * * a name in the state "conflict detected" - * * does not "logically" exist on that node. - * * No further session will be accepted on - * * that name. - * * No datagrams can be sent against that name. - * * Such an entry will not be used for - * * purposes of processing incoming request - * * packets. - * * The only valid user NetBIOS operation - * * against such a name is DELETE NAME. - * *) - * END - * NAME RELEASE REQUEST: - * IF caching is being done THEN - * BEGIN - * remove entry from cache; - * END - * NAME UPDATE REQUEST: - * IF caching is being done THEN - * BEGIN - * IF entry exists in cache already, - * update cache; - * ELSE IF name is "interesting" THEN - * BEGIN - * add entry to cache; - * END - * END - * - * NODE STATUS REQUEST: - * IF name exists in local name table THEN - * BEGIN - * (* - * * send only those names that are - * * in the same scope as the scope - * * field in the request packet - * *) - * - * send NODE STATUS RESPONSE; - * END - * END - */ static void -smb_name_process_Bnode_packet(struct name_packet *packet, - struct addr_entry *addr) +smb_name_process_Bnode_packet(struct name_packet *packet, addr_entry_t *addr) { struct name_entry *name; struct name_entry *entry; @@ -3711,372 +1908,8 @@ } } -/* - * 5.1.2.5. P-NODE INCOMING PACKET PROCESSING - * - * Processing initiated by reception of packets at a P node - * - * PROCEDURE process_incoming_packet(packet) - * - * (* - * * Processing initiated by incoming packets at a P node - * *) - * - * BEGIN - * (* - * * always ignore UDP broadcast packets - * *) - * - * IF packet was sent as a broadcast THEN - * BEGIN - * ignore packet; - * return; - * END - * CASE packet type of - * - * NAME CONFLICT DEMAND: - * IF name exists in local name table THEN - * mark name as in conflict; - * return; - * - * NAME QUERY REQUEST: - * IF name exists in local name table THEN - * BEGIN (* name exists *) - * - * (* - * * build packet - * *) - * ... - * - * (* - * * send response to the IP address and port - * * number from which the request was received. - * *) - * - * send POSITIVE_NAME_QUERY_RESPONSE ; - * return; - * END (* exists *) - * ELSE - * BEGIN (* does not exist *) - * - * (* - * * send response to the requestor - * *) - * - * send NEGATIVE_NAME_QUERY_RESPONSE ; - * return; - * END (* does not exist *) - * NODE STATUS REQUEST: - * (* - * * Name of "*" may be used for force node to - * * divulge status for administrative purposes - * *) - * IF name in local name table OR name = "*" THEN - * BEGIN - * (* - * * Build response packet and - * * send to requestor node - * * Send only those names that are - * * in the same scope as the scope - * * in the request packet. - * *) - * - * send NODE_STATUS_RESPONSE; - * END - * - * NAME RELEASE REQUEST: - * (* - * * This will be received if the NAME wants to flush the - * * name from the local name table, or from the local - * * cache. - * *) - * - * IF name exists in the local name table THEN - * BEGIN - * delete name from local name table; - * inform user that name has been deleted; - * END - * END (* case *) - * END (* procedure *) - * - * (* - * * Incoming packet processing on a NS node - * *) - * - * BEGIN - * IF packet was sent as a broadcast THEN - * BEGIN - * discard packet; - * return; - * END - * CASE packet type of - * - * NAME REGISTRATION REQUEST (UNIQUE): - * IF unique name exists in data base THEN - * BEGIN (* unique name exists *) - * (* - * * NAME node may be a "passive" - * * server in that it expects the - * * end node to do the challenge - * * server. Such a NAME node is - * * called a "non-secure" server. - * * A "secure" server will do the - * * challenging before it sends - * * back a response packet. - * *) - * - * IF non-secure THEN - * BEGIN - * (* - * * build response packet - * *) - * ... - * - * - * (* - * * let end node do the challenge - * *) - * - * send END-NODE CHALLENGE NAME REGISTRATION - * RESPONSE; - * return; - * END - * ELSE - * (* - * * secure server - do the name - * * challenge operation - * *) - * - * REPEAT - * send NAME QUERY REQUEST; - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response has been received or - * retransmit count has been exceeded - * IF no response was received THEN - * BEGIN - * - * (* node down *) - * - * update data base - remove entry; - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END - * ELSE - * BEGIN (* challenged node replied *) - * (* - * * challenged node replied with - * * a response packet - * *) - * - * CASE packet type - * - * POSITIVE NAME QUERY RESPONSE: - * - * (* - * * name still owned by the - * * challenged node - * * - * * build packet and send response - * *) - * ... - * - * - * (* - * * Note: The NAME will need to - * * keep track (based on transaction id) of - * * the IP address and port number - * * of the original requestor. - * *) - * - * send NEGATIVE NAME REGISTRATION RESPONSE; - * return; - * NEGATIVE NAME QUERY RESPONSE: - * - * update data base - remove entry; - * update data base - add new entry; - * - * (* - * * build response packet and send - * * response - * *) - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END (* case *) - * END (* challenged node replied *) - * END (* unique name exists in data base *) - * ELSE - * IF group name exists in data base THEN - * BEGIN (* group names exists *) - * - * (* - * * Members of a group name are NOT - * * challenged. - * * Make the assumption that - * * at least some of the group members - * * are still alive. - * * Refresh mechanism will - * * allow the NAME to detect when all - * * members of a group no longer use that - * * name - * *) - * - * send NEGATIVE NAME REGISTRATION RESPONSE; - * END (* group name exists *) - * ELSE - * BEGIN (* name does not exist *) - * - * (* - * * Name does not exist in data base - * * - * * This code applies to both non-secure - * * and secure server. - * *) - * - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END - * - * NAME QUERY REQUEST: - * IF name exists in data base THEN - * BEGIN - * (* - * * build response packet and send to - * * requestor - * *) - * ... - * - * send POSITIVE NAME QUERY RESPONSE; - * return; - * ELSE - * BEGIN - * (* - * * build response packet and send to - * * requestor - * *) - * ... - * - * send NEGATIVE NAME QUERY RESPONSE; - * return; - * END - * - * NAME REGISTRATION REQUEST (GROUP): - * IF name exists in data base THEN - * BEGIN - * IF local entry is a unique name THEN - * BEGIN (* local is unique *) - * - * IF non-secure THEN - * BEGIN - * send END-NODE CHALLENGE NAME - * REGISTRATION RESPONSE; - * return; - * END - * - * REPEAT - * send NAME QUERY REQUEST; - * pause(UCAST_REQ_RETRY_TIMEOUT); - * UNTIL response received or - * retransmit count exceeded - * IF no response received or - * NEGATIVE NAME QUERY RESPONSE - * received THEN - * BEGIN - * update data base - remove entry; - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END - * ELSE - * BEGIN - * (* - * * name still being held - * * by challenged node - * *) - * - * send NEGATIVE NAME REGISTRATION RESPONSE; - * END - * END (* local is unique *) - * ELSE - * BEGIN (* local is group *) - * (* - * * existing entry is a group name - * *) - * - * update data base - remove entry; - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END (* local is group *) - * END (* names exists *) - * ELSE - * BEGIN (* does not exist *) - * - * (* name does not exist in data base *) - * - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * return; - * END (* does not exist *) - * - * NAME RELEASE REQUEST: - * - * (* - * * secure server may choose to disallow - * * a node from deleting a name - * *) - * - * update data base - remove entry; - * send POSITIVE NAME RELEASE RESPONSE; - * return; - * - * NAME UPDATE REQUEST: - * - * (* - * * End-node completed a successful challenge, - * * no update database - * *) - * - * IF secure server THEN - * send NEGATIVE NAME REGISTRATION RESPONSE; - * ELSE - * BEGIN (* new entry *) - * IF entry already exists THEN - * update data base - remove entry; - * update data base - add new entry; - * send POSITIVE NAME REGISTRATION RESPONSE; - * start_timer(TTL); - * END - * - * NAME REFRESH REQUEST: - * check for consistency; - * - * IF node not allowed to have name THEN - * BEGIN - * - * (* - * * tell end node that it can't have name - * *) - * send NEGATIVE NAME REGISTRATION RESPONSE; - * END - * ELSE - * BEGIN - * - * (* - * * send confirmation response to the - * * end node. - * *) - * send POSITIVE NAME REGISTRATION; - * start_timer(TTL); - * END - * return; - * END (* case *) - * END (* procedure *) - */ static void -smb_name_process_Pnode_packet(struct name_packet *packet, - struct addr_entry *addr) +smb_name_process_Pnode_packet(struct name_packet *packet, addr_entry_t *addr) { struct name_entry *name; struct name_entry *entry; @@ -4174,102 +2007,8 @@ } } -/* - * 5.1.3.5. M-NODE INCOMING PACKET PROCESSING - * - * Processing initiated by reception of packets at a M node - * - * PROCEDURE process_incoming_packet(packet) - * - * (* - * * Processing initiated by incoming packets at a M node - * *) - * - * BEGIN - * CASE packet type of - * - * NAME CONFLICT DEMAND: - * IF name exists in local name table THEN - * mark name as in conflict; - * return; - * - * NAME QUERY REQUEST: - * IF name exists in local name table THEN - * BEGIN (* name exists *) - * - * (* - * * build packet - * *) - * ... - * - * (* - * * send response to the IP address and port - * * number from which the request was received. - * *) - * - * send POSITIVE NAME QUERY RESPONSE ; - * return; - * END (* exists *) - * ELSE - * BEGIN (* does not exist *) - * - * (* - * * send response to the requestor - * *) - * - * IF request NOT broadcast THEN - * (* - * * Don't send negative responses to - * * queries sent by B nodes - * *) - * send NEGATIVE NAME QUERY RESPONSE ; - * return; - * END (* does not exist *) - * NODE STATUS REQUEST: - * BEGIN - * (* - * * Name of "*" may be used to force node to - * * divulge status for administrative purposes - * *) - * IF name in local name table OR name = "*" THEN - * (* - * * Build response packet and - * * send to requestor node - * * Send only those names that are - * * in the same scope as the scope - * * in the request packet. - * *) - * - * send NODE STATUS RESPONSE; - * END - * - * NAME RELEASE REQUEST: - * (* - * * This will be received if the NAME wants to flush the - * * name from the local name table, or from the local - * * cache. - * *) - * - * IF name exists in the local name table THEN - * BEGIN - * delete name from local name table; - * inform user that name has been deleted; - * END - * NAME REGISTRATION REQUEST (UNIQUE): - * IF name exists in local name table THEN - * send NEGATIVE NAME REGISTRATION RESPONSE ; - * NAME REGISTRATION REQUEST (GROUP): - * IF name exists in local name table THEN - * BEGIN - * IF local entry is a unique name THEN - * send NEGATIVE NAME REGISTRATION RESPONSE ; - * END - * END (* case *) - * END (* procedure *) - */ static void -smb_name_process_Mnode_packet(struct name_packet *packet, - struct addr_entry *addr) +smb_name_process_Mnode_packet(struct name_packet *packet, addr_entry_t *addr) { if (packet->info & NAME_NM_FLAGS_B) smb_name_process_Bnode_packet(packet, addr); @@ -4278,8 +2017,7 @@ } static void -smb_name_process_Hnode_packet(struct name_packet *packet, - struct addr_entry *addr) +smb_name_process_Hnode_packet(struct name_packet *packet, addr_entry_t *addr) { if (packet->info & NAME_NM_FLAGS_B) smb_name_process_Bnode_packet(packet, addr); @@ -4319,7 +2057,6 @@ smb_netbios_cache_reset_ttl(); } - /* * smb_name_find_name * @@ -4368,7 +2105,7 @@ { int rc = 1; - smb_netbios_name_dump(name); + smb_netbios_name_logf(name); switch (smb_node_type) { case 'B': @@ -4399,9 +2136,8 @@ unsigned char type; type = name->name[15]; - if ((type != 0x00) && (type != 0x20)) { - syslog(LOG_ERR, - "netbios: error trying to delete non-local name"); + if ((type != NBT_WKSTA) && (type != NBT_SERVER)) { + syslog(LOG_DEBUG, "nbns: name delete bad type (0x%02x)", type); smb_netbios_name_logf(name); name->attributes &= ~NAME_ATTR_LOCAL; return (-1); @@ -4432,7 +2168,7 @@ } typedef struct { - struct addr_entry *addr; + addr_entry_t *addr; char *buf; int length; } worker_param_t; @@ -4447,16 +2183,16 @@ smb_netbios_worker(void *arg) { worker_param_t *p = (worker_param_t *)arg; - struct addr_entry *addr = p->addr; + addr_entry_t *addr = p->addr; struct name_packet *packet; - if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != 0) { + if ((packet = smb_name_buf_to_packet(p->buf, p->length)) != NULL) { if (packet->info & NAME_OPCODE_R) { /* Reply packet */ smb_reply_ready(packet, addr); free(p->buf); free(p); - return (0); + return (NULL); } /* Request packet */ @@ -4480,29 +2216,48 @@ smb_netbios_name_freeaddrs(packet->answer->name); free(packet); } else { - syslog(LOG_DEBUG, "SmbNBNS: error decoding received packet"); + syslog(LOG_ERR, "nbns: packet decode failed"); } free(addr); free(p->buf); free(p); - return (0); + return (NULL); } +/* + * Configure the node type. If a WINS server has been specified, + * act like an H-node. Otherwise, behave like a B-node. + */ static void -smb_netbios_wins_config(char *ip) +smb_netbios_node_config(void) { - uint32_t ipaddr; + static smb_cfg_id_t wins[SMB_PI_MAX_WINS] = { + SMB_CI_WINS_SRV1, + SMB_CI_WINS_SRV2 + }; + char ipstr[16]; + uint32_t ipaddr; + int i; - ipaddr = inet_addr(ip); - if (ipaddr != INADDR_NONE) { + smb_node_type = SMB_NODETYPE_B; + nbns_num = 0; + bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); + + for (i = 0; i < SMB_PI_MAX_WINS; ++i) { + ipstr[0] = '\0'; + (void) smb_config_getstr(wins[i], ipstr, sizeof (ipstr)); + + if ((ipaddr = inet_addr(ipstr)) == INADDR_NONE) + continue; + + smb_node_type = SMB_NODETYPE_H; smb_nbns[nbns_num].flags = ADDR_FLAG_VALID; smb_nbns[nbns_num].sinlen = sizeof (struct sockaddr_in); smb_nbns[nbns_num].sin.sin_family = AF_INET; smb_nbns[nbns_num].sin.sin_addr.s_addr = ipaddr; - smb_nbns[nbns_num++].sin.sin_port = - htons(NAME_SERVICE_UDP_PORT); - smb_node_type = SMB_NODETYPE_H; + smb_nbns[nbns_num].sin.sin_port = htons(IPPORT_NETBIOS_NS); + nbns_num++; } } @@ -4539,70 +2294,58 @@ } } +/* + * Note that the node configuration must be setup before calling + * smb_init_name_struct(). + */ void smb_netbios_name_config(void) { - struct name_entry name; - char wins_ip[16]; - smb_niciter_t ni; - int rc; + addr_entry_t *bcast_entry; + struct name_entry name; + smb_niciter_t ni; + int rc; - /* Start with no broadcast addresses */ + (void) mutex_lock(&nbt_name_config_mtx); + smb_netbios_node_config(); + bcast_num = 0; bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS); - /* Add all of the broadcast addresses */ rc = smb_nic_getfirst(&ni); while (rc == 0) { - if (ni.ni_nic.nic_smbflags & - (SMB_NICF_ALIAS | SMB_NICF_NBEXCL)) { + if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) || + (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) { rc = smb_nic_getnext(&ni); continue; } - smb_bcast_list[bcast_num].flags = ADDR_FLAG_VALID; - smb_bcast_list[bcast_num].attributes = NAME_ATTR_LOCAL; - smb_bcast_list[bcast_num].sinlen = sizeof (struct sockaddr_in); - smb_bcast_list[bcast_num].sin.sin_family = AF_INET; - smb_bcast_list[bcast_num].sin.sin_port = - htons(NAME_SERVICE_UDP_PORT); - smb_bcast_list[bcast_num++].sin.sin_addr.s_addr = - ni.ni_nic.nic_bcast; - rc = smb_nic_getnext(&ni); - } - /* Start with no WINS */ - smb_node_type = SMB_NODETYPE_B; - nbns_num = 0; - bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); - - /* add any configured WINS */ - (void) smb_config_getstr(SMB_CI_WINS_SRV1, wins_ip, sizeof (wins_ip)); - smb_netbios_wins_config(wins_ip); - (void) smb_config_getstr(SMB_CI_WINS_SRV2, wins_ip, sizeof (wins_ip)); - smb_netbios_wins_config(wins_ip); - - if (smb_nic_getfirst(&ni) != 0) - return; - - do { - if ((ni.ni_nic.nic_smbflags & SMB_NICF_NBEXCL) || - (ni.ni_nic.nic_smbflags & SMB_NICF_ALIAS)) - continue; + bcast_entry = &smb_bcast_list[bcast_num]; + bcast_entry->flags = ADDR_FLAG_VALID; + bcast_entry->attributes = NAME_ATTR_LOCAL; + bcast_entry->sinlen = sizeof (struct sockaddr_in); + bcast_entry->sin.sin_family = AF_INET; + bcast_entry->sin.sin_port = htons(IPPORT_NETBIOS_NS); + bcast_entry->sin.sin_addr.s_addr = ni.ni_nic.nic_bcast; + bcast_num++; smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host, - 0x00, 0, ni.ni_nic.nic_ip.a_ipv4, - htons(DGM_SRVC_UDP_PORT), + NBT_WKSTA, 0, ni.ni_nic.nic_ip.a_ipv4, + htons(IPPORT_NETBIOS_DGM), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name); (void) smb_netbios_cache_insert(&name); smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host, - 0x20, 0, ni.ni_nic.nic_ip.a_ipv4, - htons(DGM_SRVC_UDP_PORT), + NBT_SERVER, 0, ni.ni_nic.nic_ip.a_ipv4, + htons(IPPORT_NETBIOS_DGM), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name); (void) smb_netbios_cache_insert(&name); - } while (smb_nic_getnext(&ni) == 0); + + rc = smb_nic_getnext(&ni); + } smb_netbios_name_registration(); + (void) mutex_unlock(&nbt_name_config_mtx); } void @@ -4610,6 +2353,7 @@ { struct name_entry *name; + (void) mutex_lock(&nbt_name_config_mtx); (void) mutex_lock(&delete_queue.mtx); smb_netbios_cache_delete_locals(&delete_queue); @@ -4619,6 +2363,7 @@ free(name); } (void) mutex_unlock(&delete_queue.mtx); + (void) mutex_unlock(&nbt_name_config_mtx); } void @@ -4629,27 +2374,17 @@ } /* - * process_incoming Function: void smb_netbios_name_service_daemon(void) - * - * Description: - * - * Put test description here. - * - * Inputs: - * Nothing - * - * Returns: - * int -> Description + * NetBIOS Name Service (port 137) */ /*ARGSUSED*/ void * -smb_netbios_name_service_daemon(void *arg) +smb_netbios_name_service(void *arg) { struct sockaddr_in sin; - struct addr_entry *addr; + addr_entry_t *addr; int len; int flag = 1; - char *buf; + char *buf; worker_param_t *worker_param; smb_inaddr_t ipaddr; @@ -4659,53 +2394,43 @@ bzero(&reply_queue, sizeof (reply_queue)); reply_queue.forw = reply_queue.back = &reply_queue; - if (!smb_netbios_cache_init()) - return (0); - - bcast_num = 0; - bzero(smb_bcast_list, sizeof (addr_entry_t) * SMB_PI_MAX_NETWORKS); - if ((name_sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, - "smbd: Could not create AF_INET, SOCK_DGRAM, socket"); - smb_netbios_cache_fini(); - smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); - return (0); + syslog(LOG_ERR, "nbns: socket failed: %m"); + smb_netbios_event(NETBIOS_EVENT_ERROR); + return (NULL); } + flag = 1; + (void) setsockopt(name_sock, SOL_SOCKET, SO_REUSEADDR, &flag, + sizeof (flag)); + flag = 1; (void) setsockopt(name_sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof (flag)); bzero(&sin, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; - sin.sin_port = htons(NAME_SERVICE_UDP_PORT); + sin.sin_port = htons(IPPORT_NETBIOS_NS); if (bind(name_sock, (struct sockaddr *)&sin, sizeof (sin)) != 0) { - syslog(LOG_ERR, - "smbd: Bind to name service port %d failed (%d)", - NAME_SERVICE_UDP_PORT, errno); - smb_netbios_cache_fini(); + syslog(LOG_ERR, "nbns: bind(%d) failed: %m", + IPPORT_NETBIOS_NS); (void) close(name_sock); - smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); - return (0); + smb_netbios_event(NETBIOS_EVENT_ERROR); + return (NULL); } - smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 1); + smb_netbios_event(NETBIOS_EVENT_NS_START); - while (((nb_status.state & NETBIOS_SHUTTING_DOWN) == 0) || - (nb_status.state & NETBIOS_BROWSER_RUNNING)) { - if ((buf = malloc(MAX_DATAGRAM_LENGTH)) == 0) { - /* Sleep for 10 sec and try again */ - (void) sleep(10); + while (smb_netbios_running()) { + buf = malloc(MAX_DATAGRAM_LENGTH); + addr = malloc(sizeof (addr_entry_t)); + if ((buf == NULL) || (addr == NULL)) { + /* Sleep for 10 seconds and try again */ + free(addr); + free(buf); + smb_netbios_sleep(10); continue; } - if ((addr = (struct addr_entry *) - malloc(sizeof (struct addr_entry))) == 0) { - /* Sleep for 10 sec and try again */ - free(buf); - (void) sleep(10); - continue; - } -ignore: bzero(addr, sizeof (struct addr_entry)); +ignore: bzero(addr, sizeof (addr_entry_t)); addr->sinlen = sizeof (addr->sin); addr->forw = addr->back = addr; @@ -4713,17 +2438,16 @@ 0, (struct sockaddr *)&addr->sin, &addr->sinlen)) < 0) { if (errno == ENOMEM || errno == ENFILE || errno == EMFILE) { - /* Sleep for 10 sec and try again */ + /* Sleep for 10 seconds and try again */ free(buf); free(addr); - (void) sleep(10); + smb_netbios_sleep(10); continue; } - syslog(LOG_ERR, - "smbd: NETBIOS name service - recvfrom failed"); + syslog(LOG_ERR, "nbns: recvfrom failed: %m"); free(buf); free(addr); - smb_netbios_chg_status(NETBIOS_NAME_SVC_FAILED, 1); + smb_netbios_event(NETBIOS_EVENT_ERROR); goto shutdown; } @@ -4737,8 +2461,7 @@ /* * Launch a netbios worker to process the received packet. */ - worker_param = (worker_param_t *) - malloc(sizeof (worker_param_t)); + worker_param = malloc(sizeof (worker_param_t)); if (worker_param) { pthread_t worker; pthread_attr_t tattr; @@ -4757,23 +2480,12 @@ } shutdown: - smb_netbios_chg_status(NETBIOS_NAME_SVC_RUNNING, 0); - - (void) mutex_lock(&nb_status.mtx); - while (nb_status.state & NETBIOS_BROWSER_RUNNING) - (void) cond_wait(&nb_status.cv, &nb_status.mtx); - (void) mutex_unlock(&nb_status.mtx); + smb_netbios_event(NETBIOS_EVENT_NS_STOP); + smb_netbios_wait(NETBIOS_EVENT_BROWSER_STOP); - if ((nb_status.state & NETBIOS_NAME_SVC_FAILED) == 0) { - /* this might delay shutdown, do we want to do this? */ - /* - * it'll send name release requests but nobody's waiting - * for response and it'll eventually timeout. - */ + if (!smb_netbios_error()) smb_netbios_name_unconfig(); - } + (void) close(name_sock); - smb_netbios_cache_fini(); - syslog(LOG_DEBUG, "smbd: Netbios Name Service is down\n"); - return (0); + return (NULL); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c Mon Oct 05 11:03:34 2009 -0700 @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "@(#)smbns_netlogon.c 1.7 08/07/16 SMI" - /* * This module handles the primary domain controller location protocol. * The document claims to be version 1.15 of the browsing protocol. It also @@ -81,7 +79,7 @@ void smb_netlogon_request(struct name_entry *server, char *domain) { - nt_domain_t di; + smb_domain_t di; smb_sid_t *sid = NULL; int protocol = NETLOGON_PROTO_NETLOGON; @@ -216,13 +214,13 @@ return; } - if (domain == 0 || primary == 0) { + if (domain == NULL || primary == NULL) { syslog(LOG_ERR, "NetLogonResponse: malformed packet"); smb_msgbuf_term(&mb); return; } - syslog(LOG_DEBUG, "DC Offer Dom=%s PDC=%s From=%s", + syslog(LOG_DEBUG, "DC Offer Domain=%s PDC=%s From=%s", domain, primary, src_name); (void) mutex_lock(&ntdomain_mtx); @@ -449,8 +447,8 @@ smb_init_name_struct((unsigned char *)domain, suffix[i], 0, 0, 0, 0, 0, &dname); - syslog(LOG_DEBUG, "smb_netlogon_send"); - smb_netbios_name_dump(&dname); + syslog(LOG_DEBUG, "SmbNetlogonSend"); + smb_netbios_name_logf(&dname); if ((dest = smb_name_find_name(&dname)) != 0) { dest_dup = smb_netbios_name_dup(dest, 1); smb_name_unlock_name(dest); @@ -460,7 +458,8 @@ free(dest_dup); } } else { - syslog(LOG_DEBUG, "smbd: NBNS couldn't find %s<0x%X>", + syslog(LOG_DEBUG, + "SmbNetlogonSend: could not find %s<0x%X>", domain, suffix[i]); } } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/Makefile.com --- a/usr/src/lib/smbsrv/libsmbrdr/Makefile.com Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/Makefile.com Mon Oct 05 11:03:34 2009 -0700 @@ -19,17 +19,14 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY = libsmbrdr.a VERS = .1 OBJS_COMMON = \ - smbrdr_ipc_util.o \ smbrdr_lib.o \ smbrdr_logon.o \ smbrdr_netbios.o \ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h --- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h Mon Oct 05 11:03:34 2009 -0700 @@ -32,28 +32,8 @@ extern "C" { #endif -typedef struct smbrdr_session_info { - int si_server_os; - int si_server_lm; - int si_dc_type; -} smbrdr_session_info_t; - -/* - * Redirector IPC functions - * - * The following functions are required by the mlsvc_join to - * apply new authentication information for the authenticated IPC, rollback - * or commit the changes to the original authentication information. - */ -extern void smbrdr_ipc_set(char *, unsigned char *); -extern void smbrdr_ipc_commit(void); -extern void smbrdr_ipc_rollback(void); -extern char *smbrdr_ipc_get_user(void); -extern unsigned char *smbrdr_ipc_get_passwd(void); - - /* Redirector LOGON function */ -extern int mlsvc_logon(char *, char *, char *); +extern int smbrdr_logon(char *, char *, char *); extern int smbrdr_get_ssnkey(int, unsigned char *, size_t); /* Redirector named pipe functions */ @@ -63,10 +43,8 @@ extern int smbrdr_transact(int, char *, int, char *, int); /* Redirector session functions */ -extern void smbrdr_init(void); -extern int smbrdr_session_info(int, smbrdr_session_info_t *); -extern int mlsvc_echo(char *); -extern void mlsvc_disconnect(char *); +extern int smbrdr_echo(const char *); +extern void smbrdr_disconnect(const char *); /* DEBUG functions */ extern void smbrdr_dump_ofiles(void); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers --- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers Mon Oct 05 11:03:34 2009 -0700 @@ -39,23 +39,16 @@ SUNWprivate { global: - mlsvc_disconnect; - mlsvc_echo; - mlsvc_logon; smbrdr_close_pipe; + smbrdr_disconnect; smbrdr_dump_netuse; smbrdr_dump_ofiles; smbrdr_dump_sessions; + smbrdr_echo; smbrdr_get_ssnkey; - smbrdr_init; - smbrdr_ipc_commit; - smbrdr_ipc_get_user; - smbrdr_ipc_rollback; - smbrdr_ipc_set; - smbrdr_ipc_get_passwd; + smbrdr_logon; smbrdr_open_pipe; smbrdr_readx; - smbrdr_session_info; smbrdr_transact; local: *; diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h Mon Oct 05 11:03:34 2009 -0700 @@ -204,7 +204,7 @@ * smbrdr_session.c */ int smbrdr_negotiate(char *, char *); -struct sdb_session *smbrdr_session_lock(char *, char *, int); +struct sdb_session *smbrdr_session_lock(const char *, const char *, int); void smbrdr_session_unlock(struct sdb_session *); /* diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c Mon Oct 05 13:48:48 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The IPC connection information is encapsulated within SMB Redirector. - * Utility functions are defined here to allow other modules to get and - * set the ipc configuration, as well as, to rollback or commit the - * changes to the original authentication information. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#define SMBRDR_IPC_GETDOMAIN_TIMEOUT 10000 - -static rwlock_t smbrdr_ipc_lock; -static smbrdr_ipc_t ipc_info; -static smbrdr_ipc_t orig_ipc_info; - -static int -smbrdr_get_machine_pwd_hash(unsigned char *hash) -{ - char pwd[SMB_PASSWD_MAXLEN + 1]; - int rc = 0; - - rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); - if ((rc != SMBD_SMF_OK) || *pwd == '\0') { - return (-1); - } - - if (smb_auth_ntlm_hash(pwd, hash) != 0) - rc = -1; - - return (rc); -} - -/* - * smbrdr_ipc_init - * - * Get system configuration regarding IPC connection - * credentials and initialize related variables. - * This function will normally be called at startup - * (i.e. at the time smbrdr gets loaded). - */ -void -smbrdr_ipc_init(void) -{ - int rc; - - (void) rw_wrlock(&smbrdr_ipc_lock); - bzero(&ipc_info, sizeof (smbrdr_ipc_t)); - bzero(&orig_ipc_info, sizeof (smbrdr_ipc_t)); - - (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); - rc = smbrdr_get_machine_pwd_hash(ipc_info.passwd); - if (rc != 0) - *ipc_info.passwd = 0; - (void) rw_unlock(&smbrdr_ipc_lock); - -} - -/* - * smbrdr_ipc_set - * - * The given username and password hash will be applied to the - * ipc_info, which will be used for setting up the authenticated IPC - * channel during join domain. - * - * If domain join operation succeeds, smbrdr_ipc_commit() should be - * invoked to set the ipc_info with host credentials. Otherwise, - * smbrdr_ipc_rollback() should be called to restore the previous - * credentials. - */ -void -smbrdr_ipc_set(char *plain_user, unsigned char *passwd_hash) -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - (void) strlcpy(ipc_info.user, plain_user, sizeof (ipc_info.user)); - (void) memcpy(ipc_info.passwd, passwd_hash, SMBAUTH_HASH_SZ); - (void) rw_unlock(&smbrdr_ipc_lock); - -} - -/* - * smbrdr_ipc_commit - * - * Save the host credentials, which will be used for any authenticated - * IPC channel establishment after domain join. - * - * The host credentials is also saved to the original IPC info as - * rollback data in case the join domain process fails in the future. - */ -void -smbrdr_ipc_commit() -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - (void) smb_getsamaccount(ipc_info.user, SMB_USERNAME_MAXLEN); - (void) smbrdr_get_machine_pwd_hash(ipc_info.passwd); - (void) memcpy(&orig_ipc_info, &ipc_info, sizeof (smbrdr_ipc_t)); - (void) rw_unlock(&smbrdr_ipc_lock); -} - -/* - * smbrdr_ipc_rollback - * - * Restore the original credentials - */ -void -smbrdr_ipc_rollback() -{ - (void) rw_wrlock(&smbrdr_ipc_lock); - (void) strlcpy(ipc_info.user, orig_ipc_info.user, - sizeof (ipc_info.user)); - (void) memcpy(ipc_info.passwd, orig_ipc_info.passwd, - sizeof (ipc_info.passwd)); - (void) rw_unlock(&smbrdr_ipc_lock); -} - -/* - * Get & Set functions - */ -char * -smbrdr_ipc_get_user() -{ - char *user; - - (void) rw_rdlock(&smbrdr_ipc_lock); - user = ipc_info.user; - (void) rw_unlock(&smbrdr_ipc_lock); - return (user); -} - -unsigned char * -smbrdr_ipc_get_passwd() -{ - unsigned char *passwd; - - (void) rw_rdlock(&smbrdr_ipc_lock); - passwd = ipc_info.passwd; - (void) rw_unlock(&smbrdr_ipc_lock); - return (passwd); -} diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.h Mon Oct 05 13:48:48 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SMBSRV_IPC_UTIL_H -#define _SMBSRV_IPC_UTIL_H - -/* - * This file defines the data structure for the IPC connection and utility - * function prototypes. - */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * smbrdr_ipc_t - * - * This structure contains credentials for establishing authenticated - * IPC connection. - */ -typedef struct { - char user[SMB_USERNAME_MAXLEN]; - unsigned char passwd[SMBAUTH_HASH_SZ]; -} smbrdr_ipc_t; - - -void smbrdr_ipc_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _SMBSRV_IPC_UTIL_H */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c Mon Oct 05 11:03:34 2009 -0700 @@ -37,7 +37,6 @@ #include #include #include -#include #include #define SMBRDR_ANON_USER "IPC$" @@ -53,14 +52,12 @@ static int smbrdr_authenticate(char *, char *, char *, unsigned char *); /* - * mlsvc_logon - * * If the username is SMBRDR_ANON_USER, an anonymous session will be * established. Otherwise, an authenticated session will be established * based on the specified credentials. */ int -mlsvc_logon(char *domain_controller, char *domain, char *username) +smbrdr_logon(char *domain_controller, char *domain, char *username) { int rc; @@ -145,15 +142,15 @@ smbrdr_auth_logon(char *domain_controller, char *domain_name, char *username) { int erc; - unsigned char *pwd_hash = NULL; + uint8_t pwd_hash[SMBAUTH_HASH_SZ]; if (username == NULL || *username == 0) { syslog(LOG_DEBUG, "smbrdr_auth_logon: no username"); return (-1); } - pwd_hash = smbrdr_ipc_get_passwd(); - if (!pwd_hash || *pwd_hash == 0) { + smb_ipc_get_passwd(pwd_hash, SMBAUTH_HASH_SZ); + if (*pwd_hash == 0) { syslog(LOG_DEBUG, "smbrdr_auth_logon: no password"); return (-1); } diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,7 +43,7 @@ #include #include #include - +#include #include #include @@ -124,7 +124,7 @@ int nothing; int rc; - if (port == SMB_SRVC_TCP_PORT) + if (port == IPPORT_SMB) return (0); (void) mutex_lock(&nb_mutex); diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,8 +62,8 @@ */ static struct sdb_ofile ofile_table[N_OFILE_TABLE]; -static int mlsvc_pipe_recon_wait = 50; -static int mlsvc_pipe_recon_tries = 3; +static int smbrdr_pipe_recon_wait = 50; +static int smbrdr_pipe_recon_tries = 3; /* @@ -83,7 +83,7 @@ struct timespec st; int i; - if (mlsvc_logon(hostname, domain, username) != 0) + if (smbrdr_logon(hostname, domain, username) != 0) return (-1); /* @@ -93,7 +93,7 @@ for (i = 0; i < 2; i++) { status = smbrdr_tree_connect(hostname, username, "IPC$", &tid); if (i == 0 && status == NT_STATUS_UNEXPECTED_NETWORK_ERROR) { - if (mlsvc_logon(hostname, domain, username) != 0) + if (smbrdr_logon(hostname, domain, username) != 0) return (-1); continue; } @@ -128,7 +128,7 @@ status = NT_STATUS_OPEN_FAILED; - for (retry = 0; retry < mlsvc_pipe_recon_tries; retry++) { + for (retry = 0; retry < smbrdr_pipe_recon_tries; retry++) { status = smbrdr_ntcreatex(ofile); switch (status) { @@ -146,7 +146,7 @@ * the pipe becomes available. */ st.tv_sec = 0; - st.tv_nsec = mlsvc_pipe_recon_wait * 1000000; + st.tv_nsec = smbrdr_pipe_recon_wait * 1000000; (void) nanosleep(&st, 0); break; @@ -154,7 +154,7 @@ /* * Something else went wrong: no more retries. */ - retry = mlsvc_pipe_recon_tries; + retry = smbrdr_pipe_recon_tries; break; } } @@ -259,7 +259,7 @@ * * This function can be used when closing a share to ensure that all * ofiles resources are released. Don't call smbrdr_close_pipe because - * that will call mlsvc_smb_tdcon and we don't know what state + * that will disconnect the tree and we don't know what state * the share is in. The server will probably close all files anyway. * We are more interested in releasing the ofile resources. */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c Mon Oct 05 11:03:34 2009 -0700 @@ -47,13 +47,12 @@ #include #include #include -#include #define SMBRDR_DOMAIN_MAX 32 static uint16_t smbrdr_ports[] = { - SMB_SRVC_TCP_PORT, - SSN_SRVC_TCP_PORT + IPPORT_SMB, + IPPORT_NETBIOS_SSN }; static int smbrdr_nports = sizeof (smbrdr_ports) / sizeof (smbrdr_ports[0]); @@ -66,7 +65,7 @@ static int smbrdr_trnsprt_connect(struct sdb_session *, uint16_t); static int smbrdr_session_connect(char *, char *); static int smbrdr_smb_negotiate(struct sdb_session *); -static int smbrdr_echo(struct sdb_session *); +static int smbrdr_smb_echo(struct sdb_session *); static void smbrdr_session_disconnect(struct sdb_session *, int); @@ -77,21 +76,10 @@ } /* - * Entry pointy for smbrdr initialization. - */ -void -smbrdr_init(void) -{ - smbrdr_ipc_init(); -} - -/* - * mlsvc_disconnect - * * Disconnects the session with given server. */ void -mlsvc_disconnect(char *server) +smbrdr_disconnect(const char *server) { struct sdb_session *session; @@ -282,7 +270,7 @@ * Otherwise, we're doing NetBIOS-less SMB, i.e. SMB over TCP, * which is typically on port 445. */ - if (port == SSN_SRVC_TCP_PORT) { + if (port == IPPORT_NETBIOS_SSN) { if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) != 0) { syslog(LOG_DEBUG, "smbrdr: no hostname"); if (sock != 0) @@ -532,7 +520,7 @@ * the pointer. */ struct sdb_session * -smbrdr_session_lock(char *server, char *username, int lmode) +smbrdr_session_lock(const char *server, const char *username, int lmode) { struct sdb_session *session; int i; @@ -566,39 +554,6 @@ } /* - * smbrdr_session_info - * - * Return session information related to the specified - * named pipe (fid). - */ -int -smbrdr_session_info(int fid, smbrdr_session_info_t *si) -{ - struct sdb_session *session; - struct sdb_netuse *netuse; - struct sdb_ofile *ofile; - - if (si == NULL) - return (-1); - - if ((ofile = smbrdr_ofile_get(fid)) == NULL) { - syslog(LOG_DEBUG, - "smbrdr_session_info: unknown file (%d)", fid); - return (-1); - } - - netuse = ofile->netuse; - session = netuse->session; - - si->si_server_os = session->remote_os; - si->si_server_lm = session->remote_lm; - si->si_dc_type = session->pdc_type; - - smbrdr_ofile_put(ofile); - return (0); -} - -/* * smbrdr_dump_sessions * * Debug function to dump the session table. @@ -635,11 +590,8 @@ } } -/* - * mlsvc_echo - */ int -mlsvc_echo(char *server) +smbrdr_echo(const char *server) { struct sdb_session *session; int res = 0; @@ -647,7 +599,7 @@ if ((session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE)) == 0) return (1); - if (smbrdr_echo(session) != 0) { + if (smbrdr_smb_echo(session) != 0) { session->state = SDB_SSTATE_STALE; res = -1; } @@ -657,8 +609,6 @@ } /* - * smbrdr_echo - * * This request can be used to test the connection to the server. The * server should echo the data sent. The server should ignore the tid * in the header, so this request when there are no tree connections. @@ -667,7 +617,7 @@ * Return 0 on success. Otherwise return a -ve error code. */ static int -smbrdr_echo(struct sdb_session *session) +smbrdr_smb_echo(struct sdb_session *session) { static char *echo_str = "smbrdr"; smbrdr_handle_t srh; diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/fs/smbsrv/smb_node.c --- a/usr/src/uts/common/fs/smbsrv/smb_node.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c Mon Oct 05 11:03:34 2009 -0700 @@ -641,31 +641,31 @@ int smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags) { - int rc; + int rc = 0; smb_attr_t attr; - mutex_enter(&node->n_mutex); - - if ((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) || - (node->readonly_creator)) { - mutex_exit(&node->n_mutex); + if (node->readonly_creator) return (-1); - } bzero(&attr, sizeof (smb_attr_t)); attr.sa_mask = SMB_AT_DOSATTR; rc = smb_fsop_getattr(NULL, kcred, node, &attr); if ((rc != 0) || (attr.sa_dosattr & FILE_ATTRIBUTE_READONLY)) { - mutex_exit(&node->n_mutex); return (-1); } - crhold(cr); - node->delete_on_close_cred = cr; - node->n_delete_on_close_flags = flags; - node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; + mutex_enter(&node->n_mutex); + if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { + rc = -1; + } else { + crhold(cr); + node->delete_on_close_cred = cr; + node->n_delete_on_close_flags = flags; + node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; + rc = 0; + } mutex_exit(&node->n_mutex); - return (0); + return (rc); } void diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/fs/smbsrv/smb_server.c --- a/usr/src/uts/common/fs/smbsrv/smb_server.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_server.c Mon Oct 05 11:03:34 2009 -0700 @@ -652,7 +652,7 @@ /* * netbios must be ipv4 */ - rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT, + rc = smb_server_listen(sv, &sv->sv_nbt_daemon, IPPORT_NETBIOS_SSN, AF_INET, ioc->error); if (rc) { @@ -700,10 +700,10 @@ if (sv->sv_cfg.skc_ipv6_enable) rc = smb_server_listen(sv, &sv->sv_tcp_daemon, - SMB_SRVC_TCP_PORT, AF_INET6, ioc->error); + IPPORT_SMB, AF_INET6, ioc->error); else rc = smb_server_listen(sv, &sv->sv_tcp_daemon, - SMB_SRVC_TCP_PORT, AF_INET, ioc->error); + IPPORT_SMB, AF_INET, ioc->error); if (rc) { mutex_enter(&sv->sv_mutex); sv->sv_tcp_daemon.ld_kth = NULL; diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/fs/smbsrv/smb_session.c --- a/usr/src/uts/common/fs/smbsrv/smb_session.c Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/fs/smbsrv/smb_session.c Mon Oct 05 11:03:34 2009 -0700 @@ -314,14 +314,14 @@ return (rc); switch (session->s_local_port) { - case SSN_SRVC_TCP_PORT: + case IPPORT_NETBIOS_SSN: ret_hdr->xh_type = buf[0]; ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[3]); break; - case SMB_SRVC_TCP_PORT: + case IPPORT_SMB: ret_hdr->xh_type = buf[0]; if (ret_hdr->xh_type != 0) { @@ -358,14 +358,14 @@ } switch (session->s_local_port) { - case SSN_SRVC_TCP_PORT: + case IPPORT_NETBIOS_SSN: buf[0] = hdr->xh_type; buf[1] = ((hdr->xh_length >> 16) & 1); buf[2] = (hdr->xh_length >> 8) & 0xff; buf[3] = hdr->xh_length & 0xff; break; - case SMB_SRVC_TCP_PORT: + case IPPORT_SMB: buf[0] = hdr->xh_type; buf[1] = (hdr->xh_length >> 16) & 0xff; buf[2] = (hdr->xh_length >> 8) & 0xff; @@ -486,7 +486,7 @@ if (session == NULL) return (EINVAL); - if (session->s_local_port == SSN_SRVC_TCP_PORT) { + if (session->s_local_port == IPPORT_NETBIOS_SSN) { rc = smb_session_request(session); if (rc) { smb_rwx_rwenter(&session->s_lock, RW_WRITER); @@ -631,7 +631,7 @@ } /* - * Port will be SSN_SRVC_TCP_PORT or SMB_SRVC_TCP_PORT. + * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB. */ smb_session_t * smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv, diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/cifs.h --- a/usr/src/uts/common/smbsrv/cifs.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/cifs.h Mon Oct 05 11:03:34 2009 -0700 @@ -46,13 +46,6 @@ extern "C" { #endif - -/* - * SMB-over-TCP (NETBIOS-less SMB) TCP port - */ -#define SMB_SRVC_TCP_PORT 445 - - /* Share types */ #ifndef _SHARE_TYPES_DEFINED_ #define _SHARE_TYPES_DEFINED_ diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl --- a/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/ndl/ndrtypes.ndl Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,6 +49,10 @@ #define ARG_IS(X) [arg_is(X)] #define REFERENCE [reference] +#define REF [reference] +#define UNIQUE [unique] +#define PTR [ptr] +#define POINTER_DEFAULT(X) [pointer_default(X)] #define ANY_SIZE_ARRAY * @@ -57,6 +61,7 @@ #define BYTE uchar #define WORD ushort #define DWORD ulong +#define ntstatus_t ulong #define LPTSTR STRING wchar * @@ -101,6 +106,10 @@ #define ARG_IS(X) #define REFERENCE +#define REF +#define UNIQUE +#define PTR +#define POINTER_DEFAULT(X) #define IMPORT_EXTERN diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/ndl/samrpc.ndl --- a/usr/src/uts/common/smbsrv/ndl/samrpc.ndl Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/ndl/samrpc.ndl Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,20 +32,24 @@ #include "ndrtypes.ndl" - -#define SAMR_OPNUM_ConnectAnon 0x00 +/* Windows NT */ +#define SAMR_OPNUM_ConnectAnon 0x00 /* SamrConnect */ #define SAMR_OPNUM_CloseHandle 0x01 +#define SAMR_OPNUM_SetSecObject 0x02 #define SAMR_OPNUM_QuerySecObject 0x03 +#define SAMR_OPNUM_ShutdownSamServer 0x04 /* NotUsedOnWire */ #define SAMR_OPNUM_LookupDomain 0x05 #define SAMR_OPNUM_EnumLocalDomains 0x06 #define SAMR_OPNUM_OpenDomain 0x07 #define SAMR_OPNUM_QueryDomainInfo 0x08 +#define SAMR_OPNUM_SetDomainInfo 0x09 #define SAMR_OPNUM_CreateDomainGroup 0x0a #define SAMR_OPNUM_QueryDomainGroups 0x0b +#define SAMR_OPNUM_CreateDomainUser 0x0c #define SAMR_OPNUM_EnumDomainUsers 0x0d #define SAMR_OPNUM_CreateDomainAlias 0x0e #define SAMR_OPNUM_EnumDomainAliases 0x0f -#define SAMR_OPNUM_LookupIds 0x10 +#define SAMR_OPNUM_LookupIds 0x10 /* GetAliasMembership */ #define SAMR_OPNUM_LookupNames 0x11 #define SAMR_OPNUM_LookupDomainIds 0x12 #define SAMR_OPNUM_OpenGroup 0x13 @@ -55,6 +59,7 @@ #define SAMR_OPNUM_DeleteDomainGroup 0x17 #define SAMR_OPNUM_DeleteGroupMember 0x18 #define SAMR_OPNUM_ListGroupMembers 0x19 +#define SAMR_OPNUM_SetGroupMemberAttributes 0x1a #define SAMR_OPNUM_OpenAlias 0x1b #define SAMR_OPNUM_QueryAliasInfo 0x1c #define SAMR_OPNUM_SetAliasInfo 0x1d @@ -65,19 +70,45 @@ #define SAMR_OPNUM_OpenUser 0x22 #define SAMR_OPNUM_DeleteUser 0x23 #define SAMR_OPNUM_QueryUserInfo 0x24 +#define SAMR_OPNUM_SetUserInfo0 0x25 /* SetUserInfo */ +#define SAMR_OPNUM_ChangeUserPassword0 0x26 /* ChangeUserPassword */ #define SAMR_OPNUM_QueryUserGroups 0x27 #define SAMR_OPNUM_QueryDispInfo 0x28 /* QueryDispInfo1 */ +#define SAMR_OPNUM_GetDisplayEnumIndex 0x29 +#define SAMR_OPNUM_TestPrivateDomainFunctions 0x2a /* NotUsedOnWire */ +#define SAMR_OPNUM_TestPrivateUserFunctions 0x2b /* NotUsedOnWire */ #define SAMR_OPNUM_GetUserPwInfo 0x2c -#define SAMR_OPNUM_EnumDomainGroups 0x30 /* QueryDispInfo3 */ -#define SAMR_OPNUM_CreateUser 0x32 -#define SAMR_OPNUM_QueryDispInfo4 0x33 -#define SAMR_OPNUM_AddMultiAliasMember 0x34 -#define SAMR_OPNUM_ChangeUserPasswd 0x37 + +/* Windows 2000 */ +#define SAMR_OPNUM_RemoveMemberFromForeignDomain 0x2d +#define SAMR_OPNUM_QueryInfoDomain2 0x2e +#define SAMR_OPNUM_QueryInfoUser2 0x2f +#define SAMR_OPNUM_EnumDomainGroups 0x30 /* QueryDispInfo2 */ +#define SAMR_OPNUM_GetDisplayEnumIndex2 0x31 +#define SAMR_OPNUM_CreateUser 0x32 +#define SAMR_OPNUM_QueryDispInfo4 0x33 +#define SAMR_OPNUM_AddMultipleAliasMembers 0x34 +#define SAMR_OPNUM_RemoveMultipleAliasMembers 0x35 +#define SAMR_OPNUM_ChangeUserOemPassword 0x36 +#define SAMR_OPNUM_ChangeUserPasswd 0x37 /* UnicodePasswd */ #define SAMR_OPNUM_GetDomainPwInfo 0x38 -#define SAMR_OPNUM_Connect 0x39 +#define SAMR_OPNUM_Connect 0x39 /* SamrConnect2 */ #define SAMR_OPNUM_SetUserInfo 0x3a -#define SAMR_OPNUM_Connect3 0x3e -#define SAMR_OPNUM_Connect4 0x40 +#define SAMR_OPNUM_SetBootKeyInformation 0x3b +#define SAMR_OPNUM_GetBootKeyInformation 0x3c +#define SAMR_OPNUM_Connect2 0x3d /* SamrConnect3 */ +#define SAMR_OPNUM_Connect3 0x3e /* SamrConnect4 */ +#define SAMR_OPNUM_ChangeUserUnicodePassword3 0x3f + +/* Windows XP and Windows Server 2003 */ +#define SAMR_OPNUM_Connect4 0x40 /* SamrConnect5 */ +#define SAMR_OPNUM_RidToSid 0x41 +#define SAMR_OPNUM_SetDSRMPassword 0x42 +#define SAMR_OPNUM_ValidatePassword 0x43 + +/* Windows Vista */ +#define SAMR_OPNUM_QueryLocalizableAccountsInDomain 0x44 +#define SAMR_OPNUM_PerformGenericOperation 0x45 /* @@ -130,6 +161,10 @@ #define SAMR_ALIAS_ACCESS_DEL_MEMBER 0x00000002 #define SAMR_ALIAS_ACCESS_ADD_MEMBER 0x00000001 +#define SAMR_REVISION_1 1 /* Pre Windows 2000 */ +#define SAMR_REVISION_2 2 /* Windows 2000 */ +#define SAMR_REVISION_3 3 /* Post Windows 2000 */ + /* * Definition for a SID. The ndl compiler does not allow a typedef of * a structure containing variable size members. @@ -247,7 +282,7 @@ OPERATION(SAMR_OPNUM_Connect3) struct samr_Connect3 { IN LPTSTR servername; - IN DWORD unknown_02; + IN DWORD revision; IN DWORD access_mask; OUT samr_handle_t handle; OUT DWORD status; @@ -258,9 +293,31 @@ *********************************************************************** * SamrConnect4. A new form of connect first seen with Windows XP. * The server name is the fully qualified domain name, i.e. - * \\server.procom.com. + * \\server.sun.com. + * + * [in] DWORD InVersion, + * [in] [switch_is(InVersion)] samr_revision_info *InRevisionInfo + * [out] DWORD *OutVersion + * [out] [switch_is(*OutVersion)] *samr_revision_info *OutRevisionInfo + * + * SupportedFeatures (see notes in [MS-SAMR] + * 0x00000001 RID values returned from the server must not be + * concatenated with the domain SID. + * 0x00000002 Reserved + * 0x00000004 Reserved *********************************************************************** */ +struct samr_revision_info1 { + DWORD revision; + DWORD supported_features; +}; +typedef struct samr_revision_info1 samr_revision_info1_t; + +union samr_revision_info { + UNION_INFO_ENT(1,samr_revision_info); + DEFAULT char *nullptr; +}; + OPERATION(SAMR_OPNUM_Connect4) struct samr_Connect4 { IN LPTSTR servername; @@ -911,12 +968,10 @@ * CreateUser * * Create a user in the domain specified by the domain handle. The - * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. There - * is an unknown value at the end of the request: 0xe00500b0. + * domain handle is obtained obtained via SAMR_OPNUM_OpenDomain. + * DesiredAccess: 0xe00500b0. * The output will be a handle for use with the specified user and the - * user's RID. I think the RID may be a pointer but the value came back - * as zero once so I've padded it out so that the marshalling doesn't - * get confused. + * user's RID. I think the RID may be a unique pointer (it can be null). *********************************************************************** */ OPERATION(SAMR_OPNUM_CreateUser) @@ -924,7 +979,7 @@ IN samr_handle_t handle; IN samr_vcbuf_t username; IN DWORD account_flags; - IN DWORD unknown_e00500b0; + IN DWORD desired_access; OUT samr_handle_t user_handle; OUT DWORD maybe_ptr; OUT DWORD rid; diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/ndl/srvsvc.ndl --- a/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/ndl/srvsvc.ndl Mon Oct 05 11:03:34 2009 -0700 @@ -1056,11 +1056,11 @@ #define SV_TYPE_DIALIN_SERVER 0x00000400 #define SV_TYPE_XENIX_SERVER 0x00000800 #define SV_TYPE_SERVER_UNIX SV_TYPE_XENIX_SERVER -#define SV_TYPE_NT 0x00001000 -#define SV_TYPE_WFW 0x00002000 +#define SV_TYPE_NT 0x00001000 /* NT Workstation */ +#define SV_TYPE_WFW 0x00002000 /* Windows for Workgroups */ #define SV_TYPE_SERVER_MFPN 0x00004000 -#define SV_TYPE_SERVER_NT 0x00008000 +#define SV_TYPE_SERVER_NT 0x00008000 /* NT Server */ #define SV_TYPE_POTENTIAL_BROWSER 0x00010000 #define SV_TYPE_BACKUP_BROWSER 0x00020000 #define SV_TYPE_MASTER_BROWSER 0x00040000 @@ -1068,8 +1068,7 @@ #define SV_TYPE_SERVER_OSF 0x00100000 #define SV_TYPE_SERVER_VMS 0x00200000 #define SV_TYPE_WINDOWS 0x00400000 /* Windows95 and above */ -#define SV_TYPE_ALTERNATE_XPORT 0x20000000 /* return list for - * alternate transport */ +#define SV_TYPE_ALTERNATE_XPORT 0x20000000 /* Return alt transport list */ #define SV_TYPE_LOCAL_LIST_ONLY 0x40000000 /* Return local list only */ #define SV_TYPE_DOMAIN_ENUM 0x80000000 #define SV_TYPE_ALL 0xFFFFFFFF /* handy for NetServerEnum2 */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/ndr.h --- a/usr/src/uts/common/smbsrv/ndr.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/ndr.h Mon Oct 05 11:03:34 2009 -0700 @@ -150,6 +150,8 @@ struct ndr_stream; struct ndr_reference; +typedef uint16_t ndr_wchar_t; + typedef struct ndr_typeinfo { unsigned char version; /* sanity check */ unsigned char alignment; /* mask */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/netbios.h --- a/usr/src/uts/common/smbsrv/netbios.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/netbios.h Mon Oct 05 11:03:34 2009 -0700 @@ -58,9 +58,9 @@ * This is then encoded as a 32 byte string. * * NetBIOS Name: NetBIOS - * NetBIOS Scope: PROCOM.COM - * First Level: EOGFHEECEJEPFDCACACACACACACACACA.PROCOM.COM - * Second Level: <32>EOGFHEECEJEPFDCACACACACACACACACA<6>PROCOM<3>COM<0> + * NetBIOS Scope: DOMAIN.COM + * First Level: EOGFHEECEJEPFDCACACACACACACACACA.DOMAIN.COM + * Second Level: <32>EOGFHEECEJEPFDCACACACACACACACACA<6>DOMAIN<3>COM<0> */ #define NETBIOS_NAME_SZ 16 #define NETBIOS_ENCODED_NAME_SZ 32 @@ -71,6 +71,22 @@ ((NETBIOS_ENCODED_NAME_SZ + 2) * 2) #define NETBIOS_HDR_SZ 4 /* bytes */ + +/* + * NetBIOS name type/suffix: 16th byte of the NetBIOS name. + * The NetBIOS suffix is used by to identify computer services. + */ +#define NBT_WKSTA 0x00 /* Workstation Service */ +#define NBT_CLIENT 0x03 /* Messenger Service */ +#define NBT_RASSRVR 0x06 /* RAS Server Service */ +#define NBT_DMB 0x1B /* Domain Master Browser */ +#define NBT_IP 0x1C /* Domain Controller */ +#define NBT_MB 0x1D /* Master Browser */ +#define NBT_BS 0x1E /* Browser Elections */ +#define NBT_NETDDE 0x1F /* NetDDE Service */ +#define NBT_SERVER 0x20 /* Server Service */ +#define NBT_RASCLNT 0x21 /* RAS Client Service */ + /* * Session Packet Types (RFC 1002 4.3.1). */ @@ -107,10 +123,6 @@ #define DATAGRAM_INVALID_SOURCE_NAME_FORMAT 0x83 #define DATAGRAM_INVALID_DESTINATION_NAME_FORMAT 0x84 -#define NAME_SERVICE_TCP_PORT 137 -#define NAME_SERVICE_UDP_PORT 137 -#define DGM_SRVC_UDP_PORT 138 -#define SSN_SRVC_TCP_PORT 139 #define MAX_DATAGRAM_LENGTH 576 #define DATAGRAM_HEADER_LENGTH 14 #define DATAGRAM_ERR_HEADER_LENGTH 11 diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/smbinfo.h --- a/usr/src/uts/common/smbsrv/smbinfo.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/smbinfo.h Mon Oct 05 11:03:34 2009 -0700 @@ -42,19 +42,10 @@ #define NATIVE_OS_DEFINED #define NATIVE_OS_UNKNOWN 0x00000000 -#define NATIVE_OS_NT4_0 0x00000001 +#define NATIVE_OS_WINNT 0x00000001 #define NATIVE_OS_WIN95 0x00000002 -#define NATIVE_OS_OTHER 0x00000003 -#define NATIVE_OS_NT5_0 0x00000004 -#define NATIVE_OS_NT5_1 0x00000005 -#define NATIVE_OS_MACOS 0x00000006 - -/* - * Backward compatibility aliases. - */ -#define NATIVE_OS_WINNT NATIVE_OS_NT4_0 -#define NATIVE_OS_WIN2000 NATIVE_OS_NT5_0 -#define NATIVE_OS_WINXP NATIVE_OS_NT5_1 +#define NATIVE_OS_MACOS 0x00000003 +#define NATIVE_OS_WIN2000 0x00000004 #endif /* NATIVE_OS_DEFINED */ diff -r b17df522be57 -r fe0545fc3cdd usr/src/uts/common/smbsrv/wintypes.h --- a/usr/src/uts/common/smbsrv/wintypes.h Mon Oct 05 13:48:48 2009 -0400 +++ b/usr/src/uts/common/smbsrv/wintypes.h Mon Oct 05 11:03:34 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,6 +42,7 @@ typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; +typedef uint32_t ntstatus_t; typedef uint8_t *LPTSTR; typedef uint8_t *LPBYTE; typedef uint16_t *LPWORD;