6792084 smb_node_lookup should not take ownership of the hold on vnode passed as a parameter
6792299 winreg EnumKey should enumerate subkeys of any key
6582194 Replace getdents with readdir
6790756 smb_vss_lookup_nodes doesn't release its hold on vnode if smb_node_lookup fails
6791568 Solaris CIFS server only accepts pre-Windows 2000 user logon name
6793375 Unable to map a share with a user on a trusted domain
6796947 invalid assert in smb_vop_getattr
6581736 IPv6 support
6788345 smbadm list output only shows one trusted domain
6796594 Array overrun in libmlrpc
6797782 Need a SAM abstraction layer
6764696 Insufficient access while attempting to modify UserAccountControl attribute of a machine account
6798908 Refresh after enabling network interfaces should trigger DC discovery
6798825 Replace the smb_vop_readdir mechanism with the smb_odir_t object
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c Sun Feb 01 19:44:54 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.
*/
@@ -882,8 +882,6 @@
sr->uid_user);
mdb_printf("File: %u (%p)\n",
sr->smb_fid, sr->fid_ofile);
- mdb_printf("Dir.: %u (%p)\n", sr->smb_sid,
- sr->sid_odir);
mdb_printf("PID: %u\n", sr->smb_pid);
mdb_printf("MID: %u\n\n", sr->smb_mid);
} else {
@@ -1169,10 +1167,10 @@
"%<b>%<u>SMB odir information (%p):%</u>%</b>\n\n",
addr);
mdb_printf("State: %d (%s)\n", od->d_state, state);
- mdb_printf("SID: %u\n", od->d_sid);
+ mdb_printf("SID: %u\n", od->d_odid);
mdb_printf("Reference Count: %d\n", od->d_refcnt);
mdb_printf("Pattern: %s\n", od->d_pattern);
- mdb_printf("SMB Node: %p\n\n", od->d_dir_snode);
+ mdb_printf("SMB Node: %p\n\n", od->d_dnode);
} else {
if (DCMD_HDRSPEC(flags))
mdb_printf(
@@ -1183,7 +1181,7 @@
"ODIR", "SID", "VNODE", "PATTERN");
mdb_printf("%?p %-5u %-16s %s\n",
- addr, od->d_sid, od->d_dir_snode, od->d_pattern);
+ addr, od->d_odid, od->d_dnode, od->d_pattern);
}
}
return (DCMD_OK);
--- a/usr/src/cmd/smbsrv/smbadm/Makefile Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbadm/Makefile Sun Feb 01 19:44:54 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.
#
# ident "@(#)Makefile 1.5 08/07/16 SMI"
@@ -31,7 +31,7 @@
include ../../Makefile.cmd
include ../Makefile.smbsrv.defs
-LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lsmb -lumem -lnsl
+LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lsmb -lumem
LDFLAGS += -R/usr/lib/smbsrv
all: $(PROG)
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c Sun Feb 01 19:44:54 2009 -0700
@@ -781,7 +781,7 @@
char srvname[MAXHOSTNAMELEN];
char modename[16];
int rc;
- uint32_t srvipaddr;
+ smb_inaddr_t srvipaddr;
char ipstr[INET6_ADDRSTRLEN];
rc = smb_config_getstr(SMB_CI_SECURITY, modename, sizeof (modename));
@@ -808,9 +808,9 @@
if ((smb_get_dcinfo(srvname, MAXHOSTNAMELEN, &srvipaddr)
== NT_STATUS_SUCCESS) && (*srvname != '\0') &&
- (srvipaddr != 0)) {
- (void) inet_ntop(AF_INET, (const void *)&srvipaddr,
- ipstr, sizeof (ipstr));
+ (!smb_inet_iszero(&srvipaddr))) {
+ (void) smb_inet_ntop(&srvipaddr, ipstr,
+ SMB_IPSTRLEN(srvipaddr.a_family));
(void) printf(gettext("\t[+%s.%s] [%s]\n"),
srvname, fqdn, ipstr);
}
--- a/usr/src/cmd/smbsrv/smbd/server.xml Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbd/server.xml Sun Feb 01 19:44:54 2009 -0700
@@ -21,7 +21,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.
NOTE: This service manifest is not editable; its contents will
@@ -192,6 +192,8 @@
value='0' override='true'/>
<propval name='netlogon_seqnum' type='integer'
value='0' override='true'/>
+ <propval name='ipv6_enable' type='boolean'
+ value='false' override='true'/>
</property_group>
<!-- 6. Identify faults to be ignored. -->
--- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c Sun Feb 01 19:44:54 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 <sys/types.h>
#include <errno.h>
#include <synch.h>
@@ -86,6 +84,8 @@
adt_event_data_t *event;
au_tid_addr_t termid;
char sidbuf[SMB_SID_STRSZ];
+ char *username;
+ char *domain;
uid_t uid;
gid_t gid;
char *sid;
@@ -96,13 +96,17 @@
uid = ADT_NO_ATTRIB;
gid = ADT_NO_ATTRIB;
sid = NT_NULL_SIDSTR;
+ username = clnt->real_username;
+ domain = clnt->real_domain;
status = ADT_FAILURE;
retval = ADT_FAIL_VALUE_AUTH;
} else {
- uid = token->tkn_user->i_id;
- gid = token->tkn_primary_grp->i_id;
- smb_sid_tostr(token->tkn_user->i_sidattr.sid, sidbuf);
+ uid = token->tkn_user.i_id;
+ gid = token->tkn_primary_grp.i_id;
+ smb_sid_tostr(token->tkn_user.i_sid, sidbuf);
sid = sidbuf;
+ username = token->tkn_account_name;
+ domain = token->tkn_domain_name;
status = ADT_SUCCESS;
retval = ADT_SUCCESS;
}
@@ -123,8 +127,14 @@
(void) memset(&termid, 0, sizeof (au_tid_addr_t));
termid.at_port = clnt->local_port;
- termid.at_type = AU_IPv4;
- termid.at_addr[0] = clnt->ipaddr;
+
+ if (clnt->ipaddr.a_family == AF_INET) {
+ termid.at_addr[0] = clnt->ipaddr.a_ipv4;
+ termid.at_type = AU_IPv4;
+ } else {
+ bcopy(&clnt->ipaddr.a_ip, termid.at_addr, IPV6_ADDR_LEN);
+ termid.at_type = AU_IPv6;
+ }
adt_set_termid(ah, &termid);
if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
@@ -135,8 +145,8 @@
return (NULL);
}
- event->adt_smbd_session.domain = clnt->domain;
- event->adt_smbd_session.username = clnt->username;
+ event->adt_smbd_session.domain = domain;
+ event->adt_smbd_session.username = username;
event->adt_smbd_session.sid = sid;
if (adt_put_event(event, status, retval))
@@ -155,8 +165,8 @@
entry->sa_handle = ah;
entry->sa_uid = uid;
entry->sa_gid = gid;
- entry->sa_username = strdup(clnt->username);
- entry->sa_domain = strdup(clnt->domain);
+ entry->sa_username = strdup(username);
+ entry->sa_domain = strdup(domain);
smb_autohome_add(entry->sa_username);
smbd_audit_link(entry);
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c Sun Feb 01 19:44:54 2009 -0700
@@ -45,8 +45,6 @@
#include <time.h>
#include <libscf.h>
#include <zone.h>
-#include <time.h>
-#include <tzfile.h>
#include <libgen.h>
#include <pwd.h>
#include <grp.h>
@@ -90,6 +88,8 @@
static int smbd_refresh_init(void);
static void smbd_refresh_fini(void);
static void *smbd_refresh_monitor(void *);
+static void smbd_refresh_dc(void);
+
static pthread_t nbt_listener;
static pthread_t tcp_listener;
static pthread_t refresh_thr;
@@ -529,8 +529,6 @@
exit(SMF_EXIT_OK);
}
- syslog(LOG_DEBUG, "refresh");
-
/*
* We've been woken up by a refresh event so go do
* what is necessary.
@@ -549,9 +547,9 @@
/* re-initialize NIC table */
if (smb_nic_init() != 0)
smbd_report("failed to get NIC information");
-
smb_netbios_name_reconfig();
smb_browser_reconfig();
+ smbd_refresh_dc();
dyndns_update_zones();
if (smbd_set_netlogon_cred()) {
@@ -594,6 +592,23 @@
return (NULL);
}
+/*
+ * Update DC information on a refresh.
+ */
+static void
+smbd_refresh_dc(void)
+{
+ char fqdomain[MAXHOSTNAMELEN];
+ if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN)
+ return;
+
+ if (smb_getfqdomainname(fqdomain, MAXHOSTNAMELEN))
+ return;
+
+ if (smb_locate_dc(fqdomain, "", NULL))
+ smbd_report("DC discovery failed");
+}
+
void
smbd_set_secmode(int secmode)
{
--- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c Sun Feb 01 19:44:54 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.
*/
@@ -151,7 +151,7 @@
smb_shrlist_t lmshr_list;
smb_enumshare_info_t esi;
int offset;
- ipaddr_t ipaddr;
+ smb_inaddr_t ipaddr;
if ((cookie != SMB_SHARE_DSRV_COOKIE) || (ptr == NULL) ||
(size < sizeof (uint32_t))) {
@@ -205,15 +205,14 @@
case SMB_SHROP_GETINFO:
sharename = smb_dr_get_string(dec_ctx);
- ipaddr = smb_dr_get_uint32(dec_ctx);
+ (void) smb_dr_get_buf(dec_ctx, (unsigned char *)&ipaddr,
+ sizeof (smb_inaddr_t));
if ((dec_status = smb_dr_decode_finish(dec_ctx)) != 0) {
smb_dr_free_string(sharename);
goto decode_error;
}
-
-
rc = smb_shr_get(sharename, &lmshr_info);
- smb_shr_hostaccess(&lmshr_info, ipaddr);
+ smb_shr_hostaccess(&lmshr_info, &ipaddr);
smb_dr_put_int32(enc_ctx, SMB_SHARE_DSUCCESS);
smb_dr_put_uint32(enc_ctx, rc);
smb_dr_put_share(enc_ctx, &lmshr_info);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/common/smbsrv/smb_inet.c Sun Feb 01 19:44:54 2009 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file was originally generated using rpcgen.
+ */
+
+#ifndef _KERNEL
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#endif /* !_KERNEL */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <inet/tcp.h>
+#include <smbsrv/smb_inet.h>
+
+const struct in6_addr ipv6addr_any = IN6ADDR_ANY_INIT;
+
+boolean_t
+smb_inet_equal(smb_inaddr_t *ip1, smb_inaddr_t *ip2, uint32_t v4mask)
+{
+ if ((ip1->a_family == AF_INET) &&
+ (ip2->a_family == AF_INET) &&
+ ((ip1->a_ipv4 & v4mask) == (ip2->a_ipv4 & v4mask)))
+ return (B_TRUE);
+
+ if ((ip1->a_family == AF_INET6) &&
+ (ip2->a_family == AF_INET6) &&
+ (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, IPV6_ADDR_LEN)))
+ return (B_TRUE);
+ else
+ return (B_FALSE);
+}
+
+boolean_t
+smb_inet_iszero(smb_inaddr_t *ipaddr)
+{
+ const void *ipsz = (const void *)&ipv6addr_any;
+
+ if ((ipaddr->a_family == AF_INET) &&
+ (ipaddr->a_ipv4 == 0))
+ return (B_TRUE);
+
+ if ((ipaddr->a_family == AF_INET6) &&
+ !memcmp(&ipaddr->a_ipv6, ipsz, IPV6_ADDR_LEN))
+ return (B_TRUE);
+ else
+ return (B_FALSE);
+}
+
+const char *
+smb_inet_ntop(smb_inaddr_t *addr, char *buf, int size)
+{
+ return ((char *)inet_ntop(addr->a_family, (char *)addr, buf, size));
+}
--- a/usr/src/common/smbsrv/smb_sid.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/common/smbsrv/smb_sid.c Sun Feb 01 19:44:54 2009 -0700
@@ -19,16 +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"
-
-/*
- * NT Security Identifier (SID) library functions.
- */
-
#ifndef _KERNEL
#include <stdio.h>
#include <strings.h>
@@ -149,23 +143,26 @@
* smb_sid_split
*
* Take a full sid and split it into a domain sid and a relative id (rid).
- *
- * IMPORTANT: The original sid is modified in place - use smb_sid_dup before
- * calling this function to preserve the original SID. Be careful if you're
- * using this function in kernel code, after calling this function 'sid'
- * cannot be passed to smb_sid_free() because the size won't match the original
- * allocated size. Use smb_sid_ksplit() instead.
+ * The domain SID is allocated and a pointer to it will be returned. The
+ * RID value is passed back in 'rid' arg if it's not NULL. The allocated
+ * memory for the domain SID must be freed by caller.
*/
-int
+smb_sid_t *
smb_sid_split(smb_sid_t *sid, uint32_t *rid)
{
+ smb_sid_t *domsid;
+
if (!smb_sid_isvalid(sid) || (sid->sid_subauthcnt == 0))
- return (-1);
+ return (NULL);
- --sid->sid_subauthcnt;
+ if ((domsid = smb_sid_dup(sid)) == NULL)
+ return (NULL);
+
+ --domsid->sid_subauthcnt;
if (rid)
- *rid = sid->sid_subauth[sid->sid_subauthcnt];
- return (0);
+ *rid = domsid->sid_subauth[domsid->sid_subauthcnt];
+
+ return (domsid);
}
/*
@@ -464,3 +461,20 @@
free(sid);
#endif
}
+
+#ifndef _KERNEL
+void
+smb_ids_free(smb_ids_t *ids)
+{
+ smb_id_t *id;
+ int i;
+
+ if ((ids != NULL) && (ids->i_ids != NULL)) {
+ id = ids->i_ids;
+ for (i = 0; i < ids->i_cnt; i++, id++)
+ smb_sid_free(id->i_sid);
+
+ free(ids->i_ids);
+ }
+}
+#endif
--- a/usr/src/common/smbsrv/smb_token_xdr.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/common/smbsrv/smb_token_xdr.c Sun Feb 01 19:44:54 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"
-
/*
* This file was originally generated using rpcgen.
*/
@@ -32,65 +30,15 @@
#ifndef _KERNEL
#include <stdlib.h>
#endif /* !_KERNEL */
-#include <smbsrv/smb_vops.h>
#include <smbsrv/wintypes.h>
#include <smbsrv/smb_sid.h>
#include <smbsrv/smb_xdr.h>
#include <smbsrv/smb_token.h>
-static bool_t
-xdr_sid_helper(xdrs, sid)
- XDR *xdrs;
- char **sid;
-{
- uint32_t pos, len;
- uint8_t dummy, cnt;
- bool_t rc;
-
- switch (xdrs->x_op) {
- case XDR_DECODE:
- /*
- * chicken-and-egg: Can't use smb_sid_len() since it takes
- * SID as its parameter while sid is yet to be decoded.
- */
- pos = xdr_getpos(xdrs);
-
- if (!xdr_bool(xdrs, &rc))
- return (FALSE);
-
- if (!xdr_uint8_t(xdrs, &dummy))
- return (FALSE);
-
- if (!xdr_uint8_t(xdrs, &cnt))
- return (FALSE);
+static bool_t xdr_smb_privset_t(XDR *, smb_privset_t *);
+static bool_t xdr_smb_sid_t(XDR *, smb_sid_t *);
- rc = xdr_setpos(xdrs, pos);
-
- if (rc == FALSE)
- return (FALSE);
-
- len = sizeof (smb_sid_t) - sizeof (uint32_t) +
- (cnt * sizeof (uint32_t));
-
- if (!xdr_pointer(xdrs, sid, len, (xdrproc_t)xdr_smb_sid_t))
- return (FALSE);
- break;
-
- case XDR_ENCODE:
- case XDR_FREE:
- if (*sid == NULL)
- return (FALSE);
-
- len = smb_sid_len((smb_sid_t *)(uintptr_t)*sid);
- if (!xdr_pointer(xdrs, sid, len, (xdrproc_t)xdr_smb_sid_t))
- return (FALSE);
- break;
- }
-
- return (TRUE);
-}
-
-bool_t
+static bool_t
xdr_smb_privset_helper(xdrs, privs)
XDR *xdrs;
char **privs;
@@ -131,68 +79,45 @@
return (TRUE);
}
-bool_t
-xdr_smb_win_grps_helper(xdrs, grps)
+static bool_t
+xdr_smb_id_t(xdrs, objp)
XDR *xdrs;
- char **grps;
+ smb_id_t *objp;
{
- uint32_t pos, len;
- uint16_t cnt;
- bool_t rc;
+ uint8_t len;
- if (xdrs->x_op == XDR_DECODE) {
- pos = xdr_getpos(xdrs);
-
- if (!xdr_bool(xdrs, &rc))
- return (FALSE);
+ if ((xdrs->x_op == XDR_ENCODE) || (xdrs->x_op == XDR_FREE))
+ len = smb_sid_len(objp->i_sid);
- if (!xdr_uint16_t(xdrs, &cnt))
- return (FALSE);
+ if (!xdr_uint32_t(xdrs, &objp->i_attrs))
+ return (FALSE);
+
+ if (!xdr_uint8_t(xdrs, &len))
+ return (FALSE);
- rc = xdr_setpos(xdrs, pos);
- if (rc == FALSE)
- return (FALSE);
- } else {
- if (*grps == NULL)
- return (FALSE);
+ if (!xdr_pointer(xdrs, (char **)&objp->i_sid, len,
+ (xdrproc_t)xdr_smb_sid_t))
+ return (FALSE);
- cnt = ((smb_win_grps_t *)(uintptr_t)*grps)->wg_count;
- }
-
- len = cnt * sizeof (smb_id_t) + sizeof (smb_win_grps_t);
-
- if (!xdr_pointer(xdrs, grps, len, (xdrproc_t)xdr_smb_win_grps_t))
+ if (!xdr_uint32_t(xdrs, (uint32_t *)&objp->i_id))
return (FALSE);
return (TRUE);
}
-bool_t
-xdr_smb_id_t(xdrs, objp)
+static bool_t
+xdr_smb_ids_t(xdrs, objp)
XDR *xdrs;
- smb_id_t *objp;
+ smb_ids_t *objp;
{
- if (!xdr_smb_sid_attrs_t(xdrs, &objp->i_sidattr))
+ if (!xdr_array(xdrs, (char **)&objp->i_ids, (uint32_t *)&objp->i_cnt,
+ ~0, sizeof (smb_id_t), (xdrproc_t)xdr_smb_id_t))
return (FALSE);
- if (!xdr_uint32_t(xdrs, (uint32_t *)&objp->i_id))
- return (FALSE);
+
return (TRUE);
}
-bool_t
-xdr_smb_win_grps_t(xdrs, objp)
- XDR *xdrs;
- smb_win_grps_t *objp;
-{
- if (!xdr_uint16_t(xdrs, &objp->wg_count))
- return (FALSE);
- if (!xdr_vector(xdrs, (char *)objp->wg_groups, objp->wg_count,
- sizeof (smb_id_t), (xdrproc_t)xdr_smb_id_t))
- return (FALSE);
- return (TRUE);
-}
-
-bool_t
+static bool_t
xdr_smb_posix_grps_t(xdrs, objp)
XDR *xdrs;
smb_posix_grps_t *objp;
@@ -205,7 +130,7 @@
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_posix_grps_helper(xdrs, identity)
XDR *xdrs;
char **identity;
@@ -239,7 +164,7 @@
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_session_key_t(xdrs, objp)
XDR *xdrs;
smb_session_key_t *objp;
@@ -261,9 +186,13 @@
return (FALSE);
if (!xdr_string(xdrs, &objp->domain, ~0))
return (FALSE);
+ if (!xdr_string(xdrs, &objp->real_username, ~0))
+ return (FALSE);
+ if (!xdr_string(xdrs, &objp->real_domain, ~0))
+ return (FALSE);
if (!xdr_string(xdrs, &objp->workstation, ~0))
return (FALSE);
- if (!xdr_uint32_t(xdrs, &objp->ipaddr))
+ if (!xdr_smb_inaddr_t(xdrs, &objp->ipaddr))
return (FALSE);
if (!xdr_array(xdrs, (char **)&objp->challenge_key.challenge_key_val,
(uint32_t *)&objp->challenge_key.challenge_key_len, ~0,
@@ -283,16 +212,14 @@
return (FALSE);
if (!xdr_int(xdrs, &objp->native_lm))
return (FALSE);
- if (!xdr_uint32_t(xdrs, &objp->local_ipaddr))
+ if (!xdr_smb_inaddr_t(xdrs, &objp->local_ipaddr))
return (FALSE);
if (!xdr_uint16_t(xdrs, &objp->local_port))
return (FALSE);
- if (!xdr_uint32_t(xdrs, &objp->flags))
- return (FALSE);
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_sid_t(xdrs, objp)
XDR *xdrs;
smb_sid_t *objp;
@@ -310,7 +237,7 @@
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_luid_t(xdrs, objp)
XDR *xdrs;
smb_luid_t *objp;
@@ -322,7 +249,7 @@
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_luid_attrs_t(xdrs, objp)
XDR *xdrs;
smb_luid_attrs_t *objp;
@@ -334,7 +261,7 @@
return (TRUE);
}
-bool_t
+static bool_t
xdr_smb_privset_t(xdrs, objp)
XDR *xdrs;
smb_privset_t *objp;
@@ -351,30 +278,17 @@
}
bool_t
-xdr_smb_sid_attrs_t(xdrs, objp)
- XDR *xdrs;
- smb_sid_attrs_t *objp;
-{
- if (!xdr_uint32_t(xdrs, &objp->attrs))
- return (FALSE);
- return (xdr_sid_helper(xdrs, (char **)&objp->sid));
-}
-
-bool_t
xdr_smb_token_t(xdrs, objp)
XDR *xdrs;
smb_token_t *objp;
{
- if (!xdr_pointer(xdrs, (char **)&objp->tkn_user,
- sizeof (smb_id_t), (xdrproc_t)xdr_smb_id_t))
+ if (!xdr_smb_id_t(xdrs, &objp->tkn_user))
+ return (FALSE);
+ if (!xdr_smb_id_t(xdrs, &objp->tkn_owner))
return (FALSE);
- if (!xdr_pointer(xdrs, (char **)&objp->tkn_owner,
- sizeof (smb_id_t), (xdrproc_t)xdr_smb_id_t))
+ if (!xdr_smb_id_t(xdrs, &objp->tkn_primary_grp))
return (FALSE);
- if (!xdr_pointer(xdrs, (char **)&objp->tkn_primary_grp,
- sizeof (smb_id_t), (xdrproc_t)xdr_smb_id_t))
- return (FALSE);
- if (!xdr_smb_win_grps_helper(xdrs, (char **)&objp->tkn_win_grps))
+ if (!xdr_smb_ids_t(xdrs, &objp->tkn_win_grps))
return (FALSE);
if (!xdr_smb_privset_helper(xdrs, (char **)&objp->tkn_privileges))
return (FALSE);
--- a/usr/src/common/smbsrv/smb_xdr_utils.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/common/smbsrv/smb_xdr_utils.c Sun Feb 01 19:44:54 2009 -0700
@@ -29,7 +29,7 @@
#include <strings.h>
#endif /* _KERNEL */
#include <smbsrv/smb_xdr.h>
-
+#include <sys/socket.h>
#ifdef _KERNEL
/*
* xdr_vector():
@@ -199,6 +199,22 @@
}
bool_t
+xdr_smb_inaddr_t(XDR *xdrs, smb_inaddr_t *objp)
+{
+ if (!xdr_int32_t(xdrs, &objp->a_family))
+ return (FALSE);
+ if (objp->a_family == AF_INET) {
+ if (!xdr_uint32_t(xdrs, (in_addr_t *)&objp->a_ipv4))
+ return (FALSE);
+ } else {
+ if (!xdr_vector(xdrs, (char *)&objp->a_ipv6,
+ sizeof (objp->a_ipv6), sizeof (char), (xdrproc_t)xdr_char))
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
smb_opipe_context_xdr(XDR *xdrs, smb_opipe_context_t *objp)
{
if (!xdr_uint64_t(xdrs, &objp->oc_session_id))
@@ -217,7 +233,7 @@
return (FALSE);
if (!xdr_string(xdrs, &objp->oc_workstation, ~0))
return (FALSE);
- if (!xdr_uint32_t(xdrs, &objp->oc_ipaddr))
+ if (!xdr_smb_inaddr_t(xdrs, &objp->oc_ipaddr))
return (FALSE);
if (!xdr_int32_t(xdrs, &objp->oc_native_os))
return (FALSE);
@@ -228,7 +244,6 @@
return (TRUE);
}
-
bool_t
xdr_smb_dr_ulist_t(xdrs, objp)
XDR *xdrs;
--- a/usr/src/lib/libshare/smb/libshare_smb.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/libshare/smb/libshare_smb.c Sun Feb 01 19:44:54 2009 -0700
@@ -882,6 +882,8 @@
string_length_check_validator, SMB_REFRESH_REFRESH },
{ SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, 0 },
{ SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, path_validator, 0 },
+ { SMB_CI_IPV6_ENABLE, 0, 0, true_false_validator,
+ SMB_REFRESH_REFRESH },
};
#define SMB_OPT_NUM \
--- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c Sun Feb 01 19:44:54 2009 -0700
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -368,50 +368,6 @@
}
uint32_t
-smb_share_get(char *share_name, smb_share_t *si)
-{
- door_arg_t *arg;
- smb_dr_ctx_t *dec_ctx;
- smb_dr_ctx_t *enc_ctx;
- uint32_t rc;
-
- if ((arg = smb_share_door_clnt_enter()) == NULL)
- return (NERR_InternalError);
-
- enc_ctx = smb_dr_encode_start(arg->data_ptr, SMB_SHARE_DSIZE);
- smb_dr_put_uint32(enc_ctx, SMB_SHROP_GETINFO);
- smb_dr_put_string(enc_ctx, share_name);
-
- rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size);
- if (rc != 0) {
- smb_share_door_clnt_exit(arg, B_FALSE, "encode");
- return (NERR_InternalError);
- }
-
- if (smb_share_door_call(smb_share_dfd, arg) < 0) {
- smb_share_door_clnt_exit(arg, B_TRUE, "door call");
- return (NERR_InternalError);
- }
-
- dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size);
- if (smb_share_dchk(dec_ctx) != 0) {
- (void) smb_dr_decode_finish(dec_ctx);
- smb_share_door_clnt_exit(arg, B_FALSE, "decode");
- return (NERR_InternalError);
- }
-
- rc = smb_dr_get_uint32(dec_ctx);
- smb_dr_get_share(dec_ctx, si);
- if (smb_dr_decode_finish(dec_ctx) != 0) {
- smb_share_door_clnt_exit(arg, B_FALSE, "decode");
- return (NERR_InternalError);
- }
-
- smb_share_door_clnt_exit(arg, B_FALSE, NULL);
- return (rc);
-}
-
-uint32_t
smb_share_create(smb_share_t *si)
{
door_arg_t *arg;
--- a/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c Sun Feb 01 19:44:54 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.
*/
@@ -68,19 +68,19 @@
{
ndr_heap_t *heap;
char *base;
+ size_t allocsize = sizeof (ndr_heap_t) + NDR_HEAP_BLKSZ;
- if ((base = (char *)malloc(NDR_HEAP_BLKSZ)) == NULL)
+ if ((heap = malloc(allocsize)) == NULL)
return (NULL);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- heap = (ndr_heap_t *)base;
+ base = (char *)heap;
bzero(heap, sizeof (ndr_heap_t));
heap->iovcnt = NDR_HEAP_MAXIOV;
heap->iov = heap->iovec;
heap->iov->iov_base = base;
heap->iov->iov_len = sizeof (ndr_heap_t);
- heap->top = base + NDR_HEAP_BLKSZ;
+ heap->top = base + allocsize;
heap->next = base + sizeof (ndr_heap_t);
return (heap);
--- a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_svc.c Sun Feb 01 19:44:54 2009 -0700
@@ -285,15 +285,25 @@
struct logr_EventLogOpen *param = arg;
ndr_hdid_t *id = NULL;
ndr_handle_t *hd;
+ char *log_name = NULL;
+
+ if (param->log_name.length != 0)
+ log_name = (char *)param->log_name.str;
+
+ if ((log_name == NULL) || strcasecmp(log_name, "System") != 0) {
+ bzero(¶m->handle, sizeof (logr_handle_t));
+ param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
+ return (NDR_DRC_OK);
+ }
id = logr_hdalloc(mxa);
if (id && ((hd = logr_hdlookup(mxa, id)) != NULL)) {
hd->nh_data_free = logr_context_data_free;
bcopy(id, ¶m->handle, sizeof (logr_handle_t));
- param->status = ERROR_SUCCESS;
+ param->status = NT_STATUS_SUCCESS;
} else {
bzero(¶m->handle, sizeof (logr_handle_t));
- param->status = ERROR_ACCESS_DENIED;
+ param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
}
return (NDR_DRC_OK);
--- a/usr/src/lib/smbsrv/libmlsvc/common/eventlog_syslog.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/eventlog_syslog.c Sun Feb 01 19:44:54 2009 -0700
@@ -38,38 +38,27 @@
#include <ctype.h>
#include "eventlog.h"
-#define LOGR_SYSLOG_PARSE_ENTRY_SUCCESS 0
-#define LOGR_SYSLOG_PARSE_ENTRY_ERR -1
-#define LOGR_SYSLOG_PARSE_NOPRI_ERR -2
-
-#define LOGR_SYSLOG_PARSE_IDTOKEN_PFX "[ID"
-
typedef enum {
- LOGR_SYSLOG_MONTH = 0,
- LOGR_SYSLOG_DAY,
- LOGR_SYSLOG_TIME,
- LOGR_SYSLOG_MACHINENAME,
- LOGR_SYSLOG_SOURCE,
- LOGR_SYSLOG_ID,
- LOGR_SYSLOG_PRI_FAC,
- LOGR_SYSLOG_NARG
-} logr_syslog_tokens;
-
-typedef enum {
- LOGR_SYSLOG_FACILITY = 0,
- LOGR_SYSLOG_PRIORITY,
- LOGR_SYSLOG_PRI_FAC_NARG
-} logr_syslog_pri_fac_tokens;
+ LOGR_MONTH = 0,
+ LOGR_DAY,
+ LOGR_TIME,
+ LOGR_HOST,
+ LOGR_SOURCE,
+ LOGR_IDTAG,
+ LOGR_ID,
+ LOGR_PRI_FAC,
+ LOGR_NARG
+} logr_syslog_tokens_t;
/*
* Event code translation struct for use in processing config file
*/
-typedef struct logr_code_tbl {
- char *c_name;
- int c_val;
-} logr_code_tbl_t;
+typedef struct logr_priority {
+ char *p_name;
+ int p_value;
+} logr_priority_t;
-static logr_code_tbl_t logr_syslog_pri_names[] = {
+static logr_priority_t logr_pri_names[] = {
"panic", LOG_EMERG,
"emerg", LOG_EMERG,
"alert", LOG_ALERT,
@@ -83,233 +72,126 @@
"debug", LOG_DEBUG
};
-static logr_code_tbl_t logr_syslog_fac_names[] = {
- "kern", LOG_KERN,
- "user", LOG_USER,
- "mail", LOG_MAIL,
- "daemon", LOG_DAEMON,
- "auth", LOG_AUTH,
- "security", LOG_AUTH,
- "syslog", LOG_SYSLOG,
- "lpr", LOG_LPR,
- "news", LOG_NEWS,
- "uucp", LOG_UUCP,
- "audit", LOG_AUDIT,
- "cron", LOG_CRON,
- "local0", LOG_LOCAL0,
- "local1", LOG_LOCAL1,
- "local2", LOG_LOCAL2,
- "local3", LOG_LOCAL3,
- "local4", LOG_LOCAL4,
- "local5", LOG_LOCAL5,
- "local6", LOG_LOCAL6,
- "local7", LOG_LOCAL7
-};
-
typedef struct logr_syslog_node {
list_node_t ln_node;
char ln_logline[LOGR_MAXENTRYLEN];
} logr_syslog_node_t;
/*
- * Sets the loghost of an syslog entry.
- * Returns 0 on success, -1 on failure.
+ * Set the syslog timestamp.
+ *
+ * This is a private helper for logr_syslog_parse_entry(), which
+ * must ensure that the appropriate argv entries are non-null.
*/
-static int
-logr_syslog_set_loghost(char *log_host, logr_entry_t *le)
+static void
+logr_syslog_set_timestamp(char **argv, logr_entry_t *le)
{
- if (log_host == NULL)
- return (-1);
-
- (void) strlcpy(le->le_hostname, log_host, MAXHOSTNAMELEN);
-
- return (0);
-}
-
-/*
- * Sets the timestamp of an syslog entry.
- * Returns 0 on success, -1 on failure.
- */
-static int
-logr_syslog_set_timestamp(char *month, char *day, char *time, logr_entry_t *le)
-{
+ char *month = argv[LOGR_MONTH];
+ char *day = argv[LOGR_DAY];
+ char *time = argv[LOGR_TIME];
struct timeval now;
struct tm tm, cur_tm;
- char buf[30];
-
- if ((month == NULL) || (day == NULL) || (time == NULL))
- return (-1);
+ char buf[32];
bzero(&tm, sizeof (tm));
- (void) snprintf(buf, 30, "%s %s %s", month, day, time);
- if (strptime(buf, "%b" "%d" "%H:%M:%S", &tm) == NULL)
- return (-1);
+ (void) snprintf(buf, 32, "%s %s %s", month, day, time);
+ if (strptime(buf, "%b" "%d" "%H:%M:%S", &tm) == NULL) {
+ le->le_timestamp.tv_sec = 0;
+ return;
+ }
- /* get the current dst, year and apply it. */
- if (gettimeofday(&now, NULL) != 0)
- return (-1);
-
- if (localtime_r(&now.tv_sec, &cur_tm) == NULL)
- return (-1);
+ (void) gettimeofday(&now, NULL);
+ (void) localtime_r(&now.tv_sec, &cur_tm);
tm.tm_isdst = cur_tm.tm_isdst;
tm.tm_year = cur_tm.tm_year;
if (tm.tm_mon > cur_tm.tm_mon)
- tm.tm_year = tm.tm_year - 1;
-
- if ((le->le_timestamp.tv_sec = mktime(&tm)) == -1)
- return (-1);
-
- return (0);
-}
-
-/*
- * Sets the Priority and Facility of an syslog entry.
- * Returns 0 on success, -1 on failure.
- */
-static int
-logr_syslog_set_pri_fac(char *pf_tkn, logr_entry_t *le)
-{
- int pri_fac[LOGR_SYSLOG_PRI_FAC_NARG];
- int j, sz = 0;
-
- le->le_pri = LOG_INFO;
-
- if (pf_tkn == NULL)
- return (-1);
-
- /* Defaults */
- pri_fac[LOGR_SYSLOG_FACILITY] = LOG_USER;
- pri_fac[LOGR_SYSLOG_PRIORITY] = LOG_INFO;
+ tm.tm_year--;
- sz = sizeof (logr_syslog_fac_names) / sizeof (logr_syslog_fac_names[0]);
- for (j = 0; j < sz; j++) {
- if (strstr(pf_tkn, logr_syslog_fac_names[j].c_name) != NULL) {
- pri_fac[LOGR_SYSLOG_FACILITY] =
- logr_syslog_fac_names[j].c_val;
- break;
- }
- }
-
- sz = sizeof (logr_syslog_pri_names) / sizeof (logr_syslog_pri_names[0]);
- for (j = 0; j < sz; j++) {
- if (strstr(pf_tkn, logr_syslog_pri_names[j].c_name) != NULL) {
- pri_fac[LOGR_SYSLOG_PRIORITY] =
- logr_syslog_pri_names[j].c_val;
- break;
- }
- }
-
- le->le_pri = pri_fac[LOGR_SYSLOG_PRIORITY];
-
- return (0);
-}
-
-/*
- * Sets the messages of an syslog entry.
- */
-static void
-logr_syslog_set_message(char *logline, logr_entry_t *le)
-{
- char *p;
-
- if ((p = strchr(logline, '\n')) != NULL)
- *p = '\0';
-
- (void) strlcpy(le->le_msg, logline, LOGR_MAXENTRYLEN);
+ le->le_timestamp.tv_sec = mktime(&tm);
}
/*
- * Parses the tokens from an syslog entry. A typical syslog entry is of the
- * following standard format,
- *
- * <month> <day> <time> <loghost> <source>: [ID <ID> <facility.priority>] <msg>
- * For Example:
- * Oct 29 09:49:20 pbgalaxy1 smbd[104039]: [ID 702911 daemon.info] init done.
- *
- * This method parses the above syslog entry and populates the log_entry_t
- * structure from the parsed tokens. It returns the following return codes.
+ * Set the syslog priority.
*
- * Returns,
- * LOGR_SYSLOG_PARSE_ENTRY_ERR: If the syslog entry is NULL, or there is
- * error in parsing the entry or entry is
- * not in the standard format.
- * LOGR_SYSLOG_PARSE_NOPRI_ERR: If the priority of the message cannot be
- * obtained from the parsed tokens.
- * LOGR_SYSLOG_PARSE_ENTRY_SUCCESS: If the syslog entry is sucessfully
- * parsed.
+ * This is a private helper for logr_syslog_parse_entry(), which
+ * must ensure that the appropriate argv entries are non-null.
*/
-static int
-logr_syslog_parse_tokens(char *logline, logr_entry_t *le)
+static void
+logr_syslog_set_priority(char **argv, logr_entry_t *le)
{
- char *argv[LOGR_SYSLOG_NARG];
+ logr_priority_t *entry;
+ char *token;
+ int sz = sizeof (logr_pri_names) / sizeof (logr_pri_names[0]);
int i;
- boolean_t no_pri = B_TRUE;
+
+ le->le_pri = LOG_INFO;
- for (i = 0; i < LOGR_SYSLOG_NARG; ++i) {
- if ((argv[i] = strsep(&logline, " ")) == NULL)
- return (LOGR_SYSLOG_PARSE_ENTRY_ERR);
+ if ((token = argv[LOGR_PRI_FAC]) == NULL)
+ return;
- (void) trim_whitespace(logline);
+ for (i = 0; i < sz; i++) {
+ entry = &logr_pri_names[i];
- if ((i == LOGR_SYSLOG_ID) &&
- (strcmp(argv[i], LOGR_SYSLOG_PARSE_IDTOKEN_PFX) == 0)) {
- i--;
- no_pri = B_FALSE;
+ if (strstr(token, entry->p_name) != NULL) {
+ le->le_pri = entry->p_value;
+ break;
}
}
-
- if (logr_syslog_set_timestamp(argv[LOGR_SYSLOG_MONTH],
- argv[LOGR_SYSLOG_DAY], argv[LOGR_SYSLOG_TIME], le) < 0)
- return (LOGR_SYSLOG_PARSE_ENTRY_ERR);
-
- if (logr_syslog_set_loghost(argv[LOGR_SYSLOG_MACHINENAME], le) < 0)
- return (LOGR_SYSLOG_PARSE_ENTRY_ERR);
-
- if (no_pri)
- return (LOGR_SYSLOG_PARSE_NOPRI_ERR);
-
- if (logr_syslog_set_pri_fac(argv[LOGR_SYSLOG_PRI_FAC], le) < 0)
- return (LOGR_SYSLOG_PARSE_NOPRI_ERR);
-
- logr_syslog_set_message(logline, le);
-
- return (LOGR_SYSLOG_PARSE_ENTRY_SUCCESS);
}
/*
- * log_syslog_parse_entry
- *
- * Parse the given syslog entry into a log_entry_t structure.
+ * Parse a syslog entry into a log_entry_t structure. A typical syslog
+ * entry has one of the following formats:
*
- * Returns,
- * LOGR_SYSLOG_PARSE_ENTRY_SUCCESS: If the parsing is successful.
- * An error code less than zero, if parsing fails.
+ * <month> <day> <time> <host> <msg>
+ * <month> <day> <time> <host> <source>: [ID <ID> <facility.priority>] <msg>
+ *
+ * For Example:
+ * Oct 29 09:49:20 galaxy smbd[104039]: [ID 702911 daemon.info] init done
*/
static int
logr_syslog_parse_entry(char *logline, logr_entry_t *le)
{
- char *dup_logline;
- int ret = LOGR_SYSLOG_PARSE_ENTRY_SUCCESS;
+ char buf[LOGR_MAXENTRYLEN];
+ char *argv[LOGR_NARG];
+ char *value;
+ char *bp;
+ int i;
- if (logline == NULL)
- return (LOGR_SYSLOG_PARSE_ENTRY_ERR);
+ (void) memset(argv, 0, sizeof (char *) * LOGR_NARG);
+ (void) strlcpy(buf, logline, LOGR_MAXENTRYLEN);
- dup_logline = strdup(logline);
- ret = logr_syslog_parse_tokens(dup_logline, le);
- free(dup_logline);
+ for (bp = buf, i = 0; i < LOGR_NARG; ++i) {
+ if (i == LOGR_SOURCE) {
+ /*
+ * If the [ID key is not present, everything
+ * that follows is the message text.
+ */
+ if (strstr(bp, "[ID") == NULL)
+ break;
+ }
- switch (ret) {
- case LOGR_SYSLOG_PARSE_NOPRI_ERR:
- le->le_pri = LOG_INFO;
- logr_syslog_set_message(logline, le);
- ret = LOGR_SYSLOG_PARSE_ENTRY_SUCCESS;
- break;
- default:
- break;
+ do {
+ if ((value = strsep(&bp, " \t")) == NULL)
+ break;
+ } while (*value == '\0');
+
+ if ((argv[i] = value) == NULL)
+ return (-1);
}
- return (ret);
+ /*
+ * bp should be pointing at the remaining message text.
+ */
+ if ((value = strchr(bp, '\n')) != NULL)
+ *value = '\0';
+
+ (void) strlcpy(le->le_msg, bp, LOGR_MAXENTRYLEN);
+ (void) strlcpy(le->le_hostname, argv[LOGR_HOST], MAXHOSTNAMELEN);
+ logr_syslog_set_timestamp(argv, le);
+ logr_syslog_set_priority(argv, le);
+ return (0);
}
static void
@@ -383,8 +265,7 @@
while (node) {
entry = &log->li_entry[i];
- if (logr_syslog_parse_entry(node->ln_logline, entry) !=
- LOGR_SYSLOG_PARSE_ENTRY_SUCCESS) {
+ if (logr_syslog_parse_entry(node->ln_logline, entry) != 0) {
node = list_next(&queue, node);
continue;
}
--- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h Sun Feb 01 19:44:54 2009 -0700
@@ -48,48 +48,6 @@
extern "C" {
#endif
-typedef struct lsa_nt_domaininfo {
- smb_sid_t *n_sid;
- char n_domain[NETBIOS_NAME_SZ];
-} lsa_nt_domaininfo_t;
-
-typedef struct lsa_trusted_domainlist {
- uint32_t t_num;
- lsa_nt_domaininfo_t *t_domains;
-} lsa_trusted_domainlist_t;
-
-typedef struct lsa_dns_domaininfo {
- smb_sid_t *d_sid;
- char d_nbdomain[NETBIOS_NAME_SZ];
- char d_fqdomain[MAXHOSTNAMELEN];
- char d_forest[MAXHOSTNAMELEN];
- mslsa_guid_t d_guid;
-} lsa_dns_domaininfo_t;
-
-typedef enum lsa_info_type {
- LSA_INFO_NONE,
- LSA_INFO_PRIMARY_DOMAIN,
- LSA_INFO_ACCOUNT_DOMAIN,
- LSA_INFO_DNS_DOMAIN,
- LSA_INFO_TRUSTED_DOMAINS
-} lsa_info_type_t;
-
-typedef struct lsa_info {
- lsa_info_type_t i_type;
- union {
- lsa_nt_domaininfo_t di_primary;
- lsa_nt_domaininfo_t di_account;
- lsa_dns_domaininfo_t di_dns;
- lsa_trusted_domainlist_t di_trust;
- } i_domain;
-} lsa_info_t;
-
-extern DWORD lsa_query_primary_domain_info(char *, char *, lsa_info_t *);
-extern DWORD lsa_query_account_domain_info(char *, char *, lsa_info_t *);
-extern DWORD lsa_query_dns_domain_info(char *, char *, lsa_info_t *);
-extern DWORD lsa_enum_trusted_domains(char *, char *, lsa_info_t *);
-extern void lsa_free_info(lsa_info_t *);
-
extern uint32_t mlsvc_lookup_name(char *, smb_sid_t **, uint16_t *);
extern uint32_t mlsvc_lookup_sid(smb_sid_t *, char **);
@@ -165,12 +123,6 @@
extern void smb_autohome_add(const char *);
extern void smb_autohome_remove(const char *);
-smb_userinfo_t *mlsvc_alloc_user_info(void);
-void mlsvc_free_user_info(smb_userinfo_t *user_info);
-void mlsvc_release_user_info(smb_userinfo_t *user_info);
-void mlsvc_setadmin_user_info(smb_userinfo_t *user_info);
-char *mlsvc_sid_name_use(unsigned int snu_id);
-
/*
* A local unique id (LUID) is an opaque id used by servers to identify
* local resources, such as privileges. A client will use lookup
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c Sun Feb 01 19:44:54 2009 -0700
@@ -39,22 +39,17 @@
#include <lsalib.h>
-static uint32_t lsa_lookup_name_builtin(char *, char *, smb_userinfo_t *);
-static uint32_t lsa_lookup_name_local(char *, char *, uint16_t,
- smb_userinfo_t *);
-static uint32_t lsa_lookup_name_domain(char *, smb_userinfo_t *);
-static uint32_t lsa_lookup_name_lusr(char *, smb_sid_t **);
-static uint32_t lsa_lookup_name_lgrp(char *, smb_sid_t **);
+static uint32_t lsa_lookup_name_builtin(char *, char *, smb_account_t *);
+static uint32_t lsa_lookup_name_domain(char *, smb_account_t *);
-static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_userinfo_t *);
-static uint32_t lsa_lookup_sid_local(smb_sid_t *, smb_userinfo_t *);
-static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_userinfo_t *);
+static uint32_t lsa_lookup_sid_builtin(smb_sid_t *, smb_account_t *);
+static uint32_t lsa_lookup_sid_domain(smb_sid_t *, smb_account_t *);
static int lsa_list_accounts(mlsvc_handle_t *);
/*
* Lookup the given account and returns the account information
- * in the passed smb_userinfo_t structure.
+ * in the passed smb_account_t structure.
*
* The lookup is performed in the following order:
* well known accounts
@@ -78,7 +73,7 @@
* NT_STATUS_NONE_MAPPED Couldn't translate the account
*/
uint32_t
-lsa_lookup_name(char *account, uint16_t sid_type, smb_userinfo_t *info)
+lsa_lookup_name(char *account, uint16_t type, smb_account_t *info)
{
char nambuf[SMB_USERNAME_MAXLEN];
char dombuf[SMB_PI_MAX_DOMAIN];
@@ -105,7 +100,7 @@
status = lsa_lookup_name_builtin(domain, name, info);
if (status == NT_STATUS_NOT_FOUND) {
- status = lsa_lookup_name_local(domain, name, sid_type, info);
+ status = smb_sam_lookup_name(domain, name, type, info);
if (status == NT_STATUS_SUCCESS)
return (status);
@@ -117,18 +112,21 @@
}
uint32_t
-lsa_lookup_sid(smb_sid_t *sid, smb_userinfo_t *ainfo)
+lsa_lookup_sid(smb_sid_t *sid, smb_account_t *info)
{
+ uint32_t status;
+
if (!smb_sid_isvalid(sid))
return (NT_STATUS_INVALID_SID);
- if (smb_sid_islocal(sid))
- return (lsa_lookup_sid_local(sid, ainfo));
+ status = lsa_lookup_sid_builtin(sid, info);
+ if (status == NT_STATUS_NOT_FOUND) {
+ status = smb_sam_lookup_sid(sid, info);
+ if (status == NT_STATUS_NOT_FOUND)
+ status = lsa_lookup_sid_domain(sid, info);
+ }
- if (smb_wka_lookup_sid(sid, NULL))
- return (lsa_lookup_sid_builtin(sid, ainfo));
-
- return (lsa_lookup_sid_domain(sid, ainfo));
+ return ((status == NT_STATUS_SUCCESS) ? status : NT_STATUS_NONE_MAPPED);
}
/*
@@ -309,12 +307,14 @@
* NT_STATUS_INTERNAL_ERROR Internal error/unexpected failure
*/
static uint32_t
-lsa_lookup_name_builtin(char *domain, char *name, smb_userinfo_t *info)
+lsa_lookup_name_builtin(char *domain, char *name, smb_account_t *info)
{
smb_wka_t *wka;
char *wkadom;
- if ((wka = smb_wka_lookup(name)) == NULL)
+ bzero(info, sizeof (smb_account_t));
+
+ if ((wka = smb_wka_lookup_name(name)) == NULL)
return (NT_STATUS_NOT_FOUND);
if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
@@ -323,98 +323,17 @@
if ((domain != NULL) && (utf8_strcasecmp(domain, wkadom) != 0))
return (NT_STATUS_NONE_MAPPED);
- info->user_sid = smb_sid_dup(wka->wka_binsid);
- info->domain_sid = smb_sid_dup(wka->wka_binsid);
- info->domain_name = strdup(wkadom);
-
- if ((info->user_sid == NULL) || (info->domain_sid == NULL) ||
- (info->domain_name == NULL))
- return (NT_STATUS_NO_MEMORY);
-
- if (smb_sid_split(info->domain_sid, &info->rid) < 0)
- return (NT_STATUS_INTERNAL_ERROR);
-
- info->sid_name_use = wka->wka_type;
- return (NT_STATUS_SUCCESS);
-}
+ info->a_name = strdup(name);
+ info->a_sid = smb_sid_dup(wka->wka_binsid);
+ info->a_domain = strdup(wkadom);
+ info->a_domsid = smb_sid_split(wka->wka_binsid, &info->a_rid);
+ info->a_type = wka->wka_type;
-/*
- * Obtains the infomation for the given local account name if it
- * can be found. The type of account is specified by sid_type,
- * which can be of user, group or unknown type. If the caller
- * doesn't know whether the name is a user or group name then
- * SidTypeUnknown should be passed, in which case this
- * function first tries to find a user and then a group match.
- *
- * Return status:
- *
- * NT_STATUS_NOT_FOUND This is not a local account
- * NT_STATUS_NONE_MAPPED It's a local account but cannot be
- * translated.
- * other error status codes.
- */
-static uint32_t
-lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type,
- smb_userinfo_t *info)
-{
- char hostname[MAXHOSTNAMELEN];
- smb_sid_t *sid;
- uint32_t status;
-
- (void) smb_getnetbiosname(hostname, sizeof (hostname));
-
- if (domain != NULL) {
- if (!smb_ishostname(domain))
- return (NT_STATUS_NOT_FOUND);
-
- /* Only Netbios hostname is accepted */
- if (utf8_strcasecmp(domain, hostname) != 0)
- return (NT_STATUS_NONE_MAPPED);
+ if (!smb_account_validate(info)) {
+ smb_account_free(info);
+ return (NT_STATUS_NO_MEMORY);
}
- if ((info->domain_name = strdup(hostname)) == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- switch (sid_type) {
- case SidTypeUser:
- status = lsa_lookup_name_lusr(name, &sid);
- if (status != NT_STATUS_SUCCESS)
- return (status);
- break;
-
- case SidTypeGroup:
- case SidTypeAlias:
- status = lsa_lookup_name_lgrp(name, &sid);
- if (status != NT_STATUS_SUCCESS)
- return (status);
- break;
-
- case SidTypeUnknown:
- sid_type = SidTypeUser;
- status = lsa_lookup_name_lusr(name, &sid);
- if (status == NT_STATUS_SUCCESS)
- break;
-
- if (status == NT_STATUS_NONE_MAPPED)
- return (status);
-
- sid_type = SidTypeAlias;
- status = lsa_lookup_name_lgrp(name, &sid);
- if (status != NT_STATUS_SUCCESS)
- return (status);
- break;
-
- default:
- return (NT_STATUS_INVALID_PARAMETER);
- }
-
- info->sid_name_use = sid_type;
- info->user_sid = sid;
- info->domain_sid = smb_sid_dup(sid);
- if (info->domain_sid == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- (void) smb_sid_split(info->domain_sid, &info->rid);
return (NT_STATUS_SUCCESS);
}
@@ -426,7 +345,7 @@
* this structure.
*/
static uint32_t
-lsa_lookup_name_domain(char *account_name, smb_userinfo_t *user_info)
+lsa_lookup_name_domain(char *account_name, smb_account_t *info)
{
mlsvc_handle_t domain_handle;
smb_domain_t dinfo;
@@ -439,14 +358,13 @@
if (lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, &domain_handle) != 0)
return (NT_STATUS_INVALID_PARAMETER);
- status = lsar_lookup_names2(&domain_handle, account_name, user_info);
+ status = lsar_lookup_names2(&domain_handle, account_name, info);
if (status == NT_STATUS_REVISION_MISMATCH) {
/*
* Not a Windows 2000 domain controller:
* use the NT compatible call.
*/
- status = lsar_lookup_names(&domain_handle, account_name,
- user_info);
+ status = lsar_lookup_names(&domain_handle, account_name, info);
}
(void) lsar_close(&domain_handle);
@@ -468,8 +386,7 @@
*/
/*ARGSUSED*/
int
-lsa_lookup_privs(char *account_name, char *target_name,
- smb_userinfo_t *user_info)
+lsa_lookup_privs(char *account_name, char *target_name, smb_account_t *ainfo)
{
mlsvc_handle_t domain_handle;
int rc;
@@ -526,30 +443,6 @@
}
/*
- * lsa_test
- *
- * LSA test routine: open and close the LSA interface.
- *
- * On success 0 is returned. Otherwise a -ve error code.
- */
-int
-lsa_test(char *server, char *domain)
-{
- mlsvc_handle_t domain_handle;
- int rc;
- char *user = smbrdr_ipc_get_user();
-
- rc = lsar_open(server, domain, user, &domain_handle);
- if (rc != 0)
- return (-1);
-
- if (lsar_close(&domain_handle) != 0)
- return (-1);
-
- return (0);
-}
-
-/*
* lsa_list_accounts
*
* This function can be used to list the accounts in the specified
@@ -563,14 +456,11 @@
mlsvc_handle_t account_handle;
struct mslsa_EnumAccountBuf accounts;
struct mslsa_sid *sid;
- char *name;
- WORD sid_name_use;
- smb_userinfo_t *user_info;
+ smb_account_t ainfo;
DWORD enum_context = 0;
int rc;
int i;
- user_info = mlsvc_alloc_user_info();
bzero(&accounts, sizeof (struct mslsa_EnumAccountBuf));
do {
@@ -582,169 +472,63 @@
for (i = 0; i < accounts.entries_read; ++i) {
sid = accounts.info[i].sid;
- name = smb_wka_lookup_sid((smb_sid_t *)sid,
- &sid_name_use);
-
- if (name == 0) {
- if (lsar_lookup_sids(domain_handle, sid,
- user_info) == 0) {
- name = user_info->name;
- sid_name_use = user_info->sid_name_use;
- } else {
- name = "unknown";
- sid_name_use = SidTypeUnknown;
- }
- }
-
if (lsar_open_account(domain_handle, sid,
&account_handle) == 0) {
(void) lsar_enum_privs_account(&account_handle,
- user_info);
+ &ainfo);
(void) lsar_close(&account_handle);
}
free(accounts.info[i].sid);
- mlsvc_release_user_info(user_info);
}
if (accounts.info)
free(accounts.info);
} while (rc == 0 && accounts.entries_read != 0);
- mlsvc_free_user_info(user_info);
return (0);
}
/*
- * Lookup local SMB user account database (/var/smb/smbpasswd)
- * if there's a match query its SID from idmap service and make
- * sure the SID is a local SID.
+ * Lookup well known accounts table for the given SID
+ *
+ * Return status:
*
- * The memory for the returned SID must be freed by the caller.
+ * NT_STATUS_SUCCESS Account is translated successfully
+ * NT_STATUS_NOT_FOUND This is not a well known account
+ * NT_STATUS_NO_MEMORY Memory shortage
+ * NT_STATUS_INTERNAL_ERROR Internal error/unexpected failure
*/
static uint32_t
-lsa_lookup_name_lusr(char *name, smb_sid_t **sid)
+lsa_lookup_sid_builtin(smb_sid_t *sid, smb_account_t *ainfo)
{
- smb_passwd_t smbpw;
+ smb_wka_t *wka;
+ char *wkadom;
- if (smb_pwd_getpwnam(name, &smbpw) == NULL)
- return (NT_STATUS_NO_SUCH_USER);
+ bzero(ainfo, sizeof (smb_account_t));
+
+ if ((wka = smb_wka_lookup_sid(sid)) == NULL)
+ return (NT_STATUS_NOT_FOUND);
- if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid)
- != IDMAP_SUCCESS)
- return (NT_STATUS_NONE_MAPPED);
+ if ((wkadom = smb_wka_get_domain(wka->wka_domidx)) == NULL)
+ return (NT_STATUS_INTERNAL_ERROR);
- if (!smb_sid_islocal(*sid)) {
- smb_sid_free(*sid);
- return (NT_STATUS_NONE_MAPPED);
+ ainfo->a_name = strdup(wka->wka_name);
+ ainfo->a_sid = smb_sid_dup(wka->wka_binsid);
+ ainfo->a_domain = strdup(wkadom);
+ ainfo->a_domsid = smb_sid_split(ainfo->a_sid, &ainfo->a_rid);
+ ainfo->a_type = wka->wka_type;
+
+ if (!smb_account_validate(ainfo)) {
+ smb_account_free(ainfo);
+ return (NT_STATUS_NO_MEMORY);
}
return (NT_STATUS_SUCCESS);
}
-/*
- * Lookup local SMB group account database (/var/smb/smbgroup.db)
- * The memory for the returned SID must be freed by the caller.
- */
static uint32_t
-lsa_lookup_name_lgrp(char *name, smb_sid_t **sid)
-{
- smb_group_t grp;
-
- if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS)
- return (NT_STATUS_NO_SUCH_ALIAS);
-
- *sid = smb_sid_dup(grp.sg_id.gs_sid);
- smb_lgrp_free(&grp);
-
- return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS);
-}
-
-static uint32_t
-lsa_lookup_sid_local(smb_sid_t *sid, smb_userinfo_t *ainfo)
-{
- char hostname[MAXHOSTNAMELEN];
- smb_passwd_t smbpw;
- smb_group_t grp;
- uint32_t rid;
- uid_t id;
- int id_type;
- int rc;
-
- id_type = SMB_IDMAP_UNKNOWN;
- if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS)
- return (NT_STATUS_NONE_MAPPED);
-
- switch (id_type) {
- case SMB_IDMAP_USER:
- ainfo->sid_name_use = SidTypeUser;
- if (smb_pwd_getpwuid(id, &smbpw) == NULL)
- return (NT_STATUS_NO_SUCH_USER);
-
- ainfo->name = strdup(smbpw.pw_name);
- break;
-
- case SMB_IDMAP_GROUP:
- ainfo->sid_name_use = SidTypeAlias;
- (void) smb_sid_getrid(sid, &rid);
- rc = smb_lgrp_getbyrid(rid, SMB_LGRP_LOCAL, &grp);
- if (rc != SMB_LGRP_SUCCESS)
- return (NT_STATUS_NO_SUCH_ALIAS);
-
- ainfo->name = strdup(grp.sg_name);
- smb_lgrp_free(&grp);
- break;
-
- default:
- return (NT_STATUS_NONE_MAPPED);
- }
-
- if (ainfo->name == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- ainfo->domain_sid = smb_sid_dup(sid);
- if (smb_sid_split(ainfo->domain_sid, &ainfo->rid) < 0)
- return (NT_STATUS_INTERNAL_ERROR);
- *hostname = '\0';
- (void) smb_getnetbiosname(hostname, MAXHOSTNAMELEN);
- if ((ainfo->domain_name = strdup(hostname)) == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- return (NT_STATUS_SUCCESS);
-}
-
-static uint32_t
-lsa_lookup_sid_builtin(smb_sid_t *sid, smb_userinfo_t *ainfo)
-{
- char *name;
- WORD sid_name_use;
-
- if ((name = smb_wka_lookup_sid(sid, &sid_name_use)) == NULL)
- return (NT_STATUS_NONE_MAPPED);
-
- ainfo->sid_name_use = sid_name_use;
- ainfo->name = strdup(name);
- ainfo->domain_sid = smb_sid_dup(sid);
-
- if (ainfo->name == NULL || ainfo->domain_sid == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- if (sid_name_use != SidTypeDomain)
- (void) smb_sid_split(ainfo->domain_sid, &ainfo->rid);
-
- if ((name = smb_wka_lookup_domain(ainfo->name)) != NULL)
- ainfo->domain_name = strdup(name);
- else
- ainfo->domain_name = strdup("UNKNOWN");
-
- if (ainfo->domain_name == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- return (NT_STATUS_SUCCESS);
-}
-
-static uint32_t
-lsa_lookup_sid_domain(smb_sid_t *sid, smb_userinfo_t *ainfo)
+lsa_lookup_sid_domain(smb_sid_t *sid, smb_account_t *ainfo)
{
mlsvc_handle_t domain_handle;
char *user = smbrdr_ipc_get_user();
@@ -757,8 +541,8 @@
if (lsar_open(dinfo.d_dc, dinfo.d_nbdomain, user, &domain_handle) != 0)
return (NT_STATUS_INVALID_PARAMETER);
- status = lsar_lookup_sids2(&domain_handle,
- (struct mslsa_sid *)sid, ainfo);
+ status = lsar_lookup_sids2(&domain_handle, (struct mslsa_sid *)sid,
+ ainfo);
if (status == NT_STATUS_REVISION_MISMATCH) {
/*
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.h Sun Feb 01 19:44:54 2009 -0700
@@ -19,12 +19,12 @@
* 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_LSALIB_H
-#define _SMBSRV_LSALIB_H
+#ifndef _LSALIB_H
+#define _LSALIB_H
/*
* Prototypes for the LSA library and RPC client side library interface.
@@ -36,6 +36,7 @@
*/
#include <smbsrv/ndl/lsarpc.ndl>
+#include <smbsrv/libsmb.h>
#include <smbsrv/libmlsvc.h>
#include <smbsrv/smb_sid.h>
@@ -44,88 +45,84 @@
extern "C" {
#endif
+typedef struct lsa_nt_domaininfo {
+ smb_sid_t *n_sid;
+ char n_domain[NETBIOS_NAME_SZ];
+} lsa_nt_domaininfo_t;
+
+typedef struct lsa_trusted_domainlist {
+ uint32_t t_num;
+ lsa_nt_domaininfo_t *t_domains;
+} lsa_trusted_domainlist_t;
+
+typedef struct lsa_dns_domaininfo {
+ smb_sid_t *d_sid;
+ char d_nbdomain[NETBIOS_NAME_SZ];
+ char d_fqdomain[MAXHOSTNAMELEN];
+ char d_forest[MAXHOSTNAMELEN];
+ mslsa_guid_t d_guid;
+} lsa_dns_domaininfo_t;
+
+typedef enum lsa_info_type {
+ LSA_INFO_NONE,
+ LSA_INFO_PRIMARY_DOMAIN,
+ LSA_INFO_ACCOUNT_DOMAIN,
+ LSA_INFO_DNS_DOMAIN,
+ LSA_INFO_TRUSTED_DOMAINS
+} lsa_info_type_t;
+
+typedef struct lsa_info {
+ lsa_info_type_t i_type;
+ union {
+ lsa_nt_domaininfo_t di_primary;
+ lsa_nt_domaininfo_t di_account;
+ lsa_dns_domaininfo_t di_dns;
+ lsa_trusted_domainlist_t di_trust;
+ } i_domain;
+} lsa_info_t;
+
/*
* lsalib.c
*/
-extern uint32_t lsa_lookup_name(char *, uint16_t, smb_userinfo_t *);
-extern uint32_t lsa_lookup_sid(smb_sid_t *, smb_userinfo_t *);
-extern int lsa_lookup_privs(char *, char *, smb_userinfo_t *);
-extern int lsa_test(char *, char *);
+uint32_t lsa_lookup_name(char *, uint16_t, smb_account_t *);
+uint32_t lsa_lookup_sid(smb_sid_t *, smb_account_t *);
+void lsa_free_info(lsa_info_t *);
+DWORD lsa_query_primary_domain_info(char *, char *, lsa_info_t *);
+DWORD lsa_query_account_domain_info(char *, char *, lsa_info_t *);
+DWORD lsa_query_dns_domain_info(char *, char *, lsa_info_t *);
+DWORD lsa_enum_trusted_domains(char *, char *, lsa_info_t *);
+
/*
* lsar_open.c
*/
-int lsar_open(char *server,
- char *domain,
- char *username,
- mlsvc_handle_t *domain_handle);
-
-int lsar_open_policy2(char *server,
- char *domain,
- char *username,
- mlsvc_handle_t *lsa_handle);
-
-int lsar_open_account(mlsvc_handle_t *lsa_handle,
- struct mslsa_sid *sid,
- mlsvc_handle_t *lsa_account_handle);
-
-int lsar_close(mlsvc_handle_t *lsa_handle);
-
+int lsar_open(char *, char *, char *, mlsvc_handle_t *);
+int lsar_open_policy2(char *, char *, char *, mlsvc_handle_t *);
+int lsar_open_account(mlsvc_handle_t *, struct mslsa_sid *, mlsvc_handle_t *);
+int lsar_close(mlsvc_handle_t *);
/*
* lsar_lookup.c
*/
-int lsar_query_security_desc(mlsvc_handle_t *lsa_handle);
-
-DWORD lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
- lsa_info_t *);
-
-uint32_t lsar_lookup_names(mlsvc_handle_t *lsa_handle,
- char *name,
- smb_userinfo_t *user_info);
-
-uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle,
- struct mslsa_sid *sid,
- smb_userinfo_t *user_info);
-
-DWORD lsar_get_userid(char *server, char *name);
-
-int lsar_enum_accounts(mlsvc_handle_t *lsa_handle,
- DWORD *enum_context,
- struct mslsa_EnumAccountBuf *accounts);
-
-DWORD lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle,
- DWORD *enum_context, lsa_info_t *);
+int lsar_query_security_desc(mlsvc_handle_t *);
+DWORD lsar_query_info_policy(mlsvc_handle_t *, WORD, lsa_info_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 *,
+ smb_account_t *);
+uint32_t lsar_lookup_sids2(mlsvc_handle_t *, struct mslsa_sid *,
+ smb_account_t *);
-int lsar_enum_privs_account(mlsvc_handle_t *account_handle,
- smb_userinfo_t *user_info);
-
-int lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle,
- char *name,
- struct ms_luid *luid);
-
-int lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle,
- struct ms_luid *luid,
- char *name,
- int namelen);
-
-DWORD lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle,
- char *name,
- char *display_name,
- int display_len);
-
-uint32_t lsar_lookup_sids2(mlsvc_handle_t *lsa_handle,
- struct mslsa_sid *sid,
- smb_userinfo_t *user_info);
-
-uint32_t lsar_lookup_names2(mlsvc_handle_t *lsa_handle,
- char *name,
- smb_userinfo_t *user_info);
-
+int lsar_enum_accounts(mlsvc_handle_t *, DWORD *,
+ struct mslsa_EnumAccountBuf *);
+DWORD lsar_enum_trusted_domains(mlsvc_handle_t *, DWORD *, lsa_info_t *);
+int lsar_enum_privs_account(mlsvc_handle_t *, smb_account_t *);
+int lsar_lookup_priv_value(mlsvc_handle_t *, char *, struct ms_luid *);
+int lsar_lookup_priv_name(mlsvc_handle_t *, struct ms_luid *, char *, int);
+DWORD lsar_lookup_priv_display_name(mlsvc_handle_t *, char *, char *, int);
#ifdef __cplusplus
}
#endif
-
-#endif /* _SMBSRV_LSALIB_H */
+#endif /* _LSALIB_H */
--- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c Sun Feb 01 19:44:54 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.
*/
@@ -188,24 +188,21 @@
* NT_STATUS_NONE_MAPPED.
*/
uint32_t
-lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name,
- smb_userinfo_t *user_info)
+lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
{
- int opnum;
- int index;
- uint32_t status;
struct mslsa_LookupNames arg;
- size_t length;
- lookup_name_table_t name_table;
struct mslsa_rid_entry *rid_entry;
struct mslsa_domain_entry *domain_entry;
+ lookup_name_table_t name_table;
+ uint32_t status = NT_STATUS_SUCCESS;
+ int opnum;
+ size_t length;
char *p;
- if (lsa_handle == NULL || name == NULL || user_info == NULL)
+ if (lsa_handle == NULL || name == NULL || info == NULL)
return (NT_STATUS_INVALID_PARAMETER);
- bzero(user_info, sizeof (smb_userinfo_t));
- user_info->sid_name_use = SidTypeUnknown;
+ bzero(info, sizeof (smb_account_t));
opnum = LSARPC_OPNUM_LookupNames;
@@ -248,34 +245,39 @@
name_table.name[0].str = (unsigned char *)name;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
ndr_rpc_status(lsa_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- } else if (arg.mapped_count == 0) {
- user_info->sid_name_use = SidTypeInvalid;
- status = NT_STATUS_NONE_MAPPED;
- } else {
- rid_entry = &arg.translated_sids.rids[0];
- user_info->sid_name_use = rid_entry->sid_name_use;
- user_info->rid = rid_entry->rid;
- user_info->name = MEM_STRDUP("ndr", name);
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- if ((index = rid_entry->domain_index) == -1) {
- user_info->domain_sid = 0;
- user_info->domain_name = 0;
- } else {
- domain_entry =
- &arg.domain_table->entries[index];
- user_info->domain_sid = smb_sid_dup(
- (smb_sid_t *)domain_entry->domain_sid);
- user_info->domain_name = MEM_STRDUP("ndr",
- (const char *)
- domain_entry->domain_name.str);
- user_info->user_sid = smb_sid_splice(
- user_info->domain_sid, user_info->rid);
- }
- status = NT_STATUS_SUCCESS;
+ rid_entry = &arg.translated_sids.rids[0];
+ if (rid_entry->domain_index != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
+
+ info->a_type = rid_entry->sid_name_use;
+ info->a_name = strdup(name);
+ info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+ info->a_domain = strdup((const char *)domain_entry->domain_name.str);
+ info->a_rid = rid_entry->rid;
+ info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
+
+ if (!smb_account_validate(info)) {
+ smb_account_free(info);
+ status = NT_STATUS_NO_MEMORY;
}
ndr_rpc_release(lsa_handle);
@@ -293,19 +295,19 @@
*/
uint32_t
lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
- smb_userinfo_t *user_info)
+ smb_account_t *account)
{
struct mslsa_LookupSids arg;
struct mslsa_lup_sid_entry sid_entry;
struct mslsa_name_entry *name_entry;
struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
int opnum;
- int index;
- uint32_t status;
- if (lsa_handle == NULL || sid == NULL || user_info == NULL)
+ if (lsa_handle == NULL || sid == NULL || account == NULL)
return (NT_STATUS_INVALID_PARAMETER);
+ bzero(account, sizeof (smb_account_t));
opnum = LSARPC_OPNUM_LookupSids;
bzero(&arg, sizeof (struct mslsa_LookupSids));
@@ -317,43 +319,38 @@
arg.lup_sid_table.entries = &sid_entry;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.mapped_count == 0) {
- user_info->sid_name_use = SidTypeInvalid;
- status = NT_STATUS_NONE_MAPPED;
- } else if (arg.status != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
ndr_rpc_status(lsa_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- } else {
- name_entry = &arg.name_table.entries[0];
- user_info->sid_name_use = name_entry->sid_name_use;
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
- if (user_info->sid_name_use == SidTypeUser ||
- user_info->sid_name_use == SidTypeGroup ||
- user_info->sid_name_use == SidTypeAlias) {
-
- user_info->rid =
- sid->SubAuthority[sid->SubAuthCount - 1];
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- user_info->name = MEM_STRDUP("ndr",
- (const char *)name_entry->name.str);
- }
+ name_entry = &arg.name_table.entries[0];
+ if (name_entry->domain_ix != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
- if ((index = name_entry->domain_ix) == -1) {
- user_info->domain_sid = 0;
- user_info->domain_name = 0;
- } else {
- domain_entry =
- &arg.domain_table->entries[index];
+ account->a_type = name_entry->sid_name_use;
+ account->a_name = strdup((char const *)name_entry->name.str);
+ account->a_sid = smb_sid_dup((smb_sid_t *)sid);
+ account->a_domain = strdup((char const *)domain_entry->domain_name.str);
+ account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
- user_info->domain_sid = smb_sid_dup(
- (smb_sid_t *)domain_entry->domain_sid);
-
- user_info->domain_name = MEM_STRDUP("ndr",
- (const char *)
- domain_entry->domain_name.str);
- }
- status = NT_STATUS_SUCCESS;
+ if (!smb_account_validate(account)) {
+ smb_account_free(account);
+ status = NT_STATUS_NO_MEMORY;
}
ndr_rpc_release(lsa_handle);
@@ -496,8 +493,7 @@
*/
/*ARGSUSED*/
int
-lsar_enum_privs_account(mlsvc_handle_t *account_handle,
- smb_userinfo_t *user_info)
+lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
{
struct mslsa_EnumPrivsAccount arg;
int opnum;
@@ -659,21 +655,21 @@
/*
* lsar_lookup_sids2
*/
-DWORD
+uint32_t
lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
- smb_userinfo_t *user_info)
+ smb_account_t *account)
{
struct lsar_lookup_sids2 arg;
struct lsar_name_entry2 *name_entry;
struct mslsa_lup_sid_entry sid_entry;
struct mslsa_domain_entry *domain_entry;
+ uint32_t status = NT_STATUS_SUCCESS;
int opnum;
- int index;
- DWORD status;
- if (lsa_handle == NULL || sid == NULL || user_info == NULL)
+ if (lsa_handle == NULL || sid == NULL || account == NULL)
return (NT_STATUS_INVALID_PARAMETER);
+ bzero(account, sizeof (smb_account_t));
opnum = LSARPC_OPNUM_LookupSids2;
if (ndr_rpc_server_os(lsa_handle) != NATIVE_OS_WIN2000)
@@ -689,42 +685,38 @@
arg.requested_count = arg.lup_sid_table.n_entry;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.mapped_count == 0) {
- user_info->sid_name_use = SidTypeInvalid;
- status = NT_STATUS_NONE_MAPPED;
- } else if (arg.status != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
ndr_rpc_status(lsa_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- } else {
- name_entry = &arg.name_table.entries[0];
- user_info->sid_name_use = name_entry->sid_name_use;
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
- if (user_info->sid_name_use == SidTypeUser ||
- user_info->sid_name_use == SidTypeGroup ||
- user_info->sid_name_use == SidTypeAlias) {
-
- user_info->rid =
- sid->SubAuthority[sid->SubAuthCount - 1];
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- user_info->name = MEM_STRDUP("ndr",
- (char const *)name_entry->name.str);
+ name_entry = &arg.name_table.entries[0];
+ if (name_entry->domain_ix != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- }
+ domain_entry = &arg.domain_table->entries[0];
- if ((index = name_entry->domain_ix) == -1) {
- user_info->domain_sid = 0;
- user_info->domain_name = 0;
- } else {
- domain_entry = &arg.domain_table->entries[index];
+ account->a_type = name_entry->sid_name_use;
+ account->a_name = strdup((char const *)name_entry->name.str);
+ account->a_sid = smb_sid_dup((smb_sid_t *)sid);
+ account->a_domain = strdup((char const *)domain_entry->domain_name.str);
+ account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
- user_info->domain_sid = smb_sid_dup(
- (smb_sid_t *)domain_entry->domain_sid);
-
- user_info->domain_name = MEM_STRDUP("ndr",
- (char const *)domain_entry->domain_name.str);
- }
- status = NT_STATUS_SUCCESS;
+ if (!smb_account_validate(account)) {
+ smb_account_free(account);
+ status = NT_STATUS_NO_MEMORY;
}
ndr_rpc_release(lsa_handle);
@@ -749,23 +741,20 @@
* It should be okay to lookup DOMAIN\Administrator in this function.
*/
uint32_t
-lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name,
- smb_userinfo_t *user_info)
+lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
{
- int opnum;
- int index;
struct lsar_LookupNames2 arg;
- size_t length;
- lookup_name_table_t name_table;
struct lsar_rid_entry2 *rid_entry;
struct mslsa_domain_entry *domain_entry;
- uint32_t status;
+ lookup_name_table_t name_table;
+ uint32_t status = NT_STATUS_SUCCESS;
+ size_t length;
+ int opnum;
- if (lsa_handle == NULL || name == NULL || user_info == NULL)
+ if (lsa_handle == NULL || name == NULL || info == NULL)
return (NT_STATUS_INVALID_PARAMETER);
- bzero(user_info, sizeof (smb_userinfo_t));
- user_info->sid_name_use = SidTypeUnknown;
+ bzero(info, sizeof (smb_account_t));
opnum = LSARPC_OPNUM_LookupNames2;
@@ -786,39 +775,45 @@
name_table.name[0].str = (unsigned char *)name;
if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
- status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (arg.status != NT_STATUS_SUCCESS) {
ndr_rpc_status(lsa_handle, opnum, arg.status);
- status = NT_SC_VALUE(arg.status);
- } else if (arg.mapped_count == 0) {
- user_info->sid_name_use = SidTypeInvalid;
- status = NT_STATUS_NONE_MAPPED;
- } else {
- rid_entry = &arg.translated_sids.rids[0];
- user_info->sid_name_use = rid_entry->sid_name_use;
- user_info->rid = rid_entry->rid;
- user_info->name = MEM_STRDUP("ndr", name);
+ ndr_rpc_release(lsa_handle);
+ return (NT_SC_VALUE(arg.status));
+ }
+
+ if (arg.mapped_count == 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
- if ((index = rid_entry->domain_index) == -1) {
- user_info->domain_sid = 0;
- user_info->domain_name = 0;
- } else {
- domain_entry = &arg.domain_table->entries[index];
+ rid_entry = &arg.translated_sids.rids[0];
+ if (rid_entry->domain_index != 0) {
+ ndr_rpc_release(lsa_handle);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ domain_entry = &arg.domain_table->entries[0];
- user_info->domain_sid = smb_sid_dup(
- (smb_sid_t *)domain_entry->domain_sid);
+ info->a_type = rid_entry->sid_name_use;
+ info->a_name = strdup(name);
+ info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
+ info->a_domain = strdup((char const *)domain_entry->domain_name.str);
+ info->a_rid = rid_entry->rid;
+ info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
- user_info->domain_name = MEM_STRDUP("ndr",
- (char const *)domain_entry->domain_name.str);
- user_info->user_sid = smb_sid_splice(
- user_info->domain_sid, user_info->rid);
- }
- status = NT_STATUS_SUCCESS;
+ if (!smb_account_validate(info)) {
+ smb_account_free(info);
+ status = NT_STATUS_NO_MEMORY;
}
ndr_rpc_release(lsa_handle);
return (status);
}
+
static void
lsar_set_nt_domaininfo(smb_sid_t *sid, char *nb_domain,
lsa_nt_domaininfo_t *info)
--- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers Sun Feb 01 19:44:54 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.
#
#
@@ -27,11 +27,6 @@
SUNWprivate {
global:
dssetup_clear_domain_info;
- lsa_enum_trusted_domains;
- lsa_free_info;
- lsa_query_account_domain_info;
- lsa_query_dns_domain_info;
- lsa_query_primary_domain_info;
mlsvc_get_door_fd;
mlsvc_get_num_users;
mlsvc_get_user_list;
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_domain.c Sun Feb 01 19:44:54 2009 -0700
@@ -519,6 +519,8 @@
if (lsa_query_primary_domain_info(server, domain, &info)
== NT_STATUS_SUCCESS) {
+ nt_domain_flush(NT_DOMAIN_PRIMARY);
+
nt_info = &info.i_domain.di_primary;
smb_domain_update_tabent(NT_DOMAIN_PRIMARY, nt_info);
lsa_free_info(&info);
@@ -526,6 +528,8 @@
if (lsa_query_account_domain_info(server, domain, &info)
== NT_STATUS_SUCCESS) {
+ nt_domain_flush(NT_DOMAIN_ACCOUNT);
+
nt_info = &info.i_domain.di_account;
smb_domain_update_tabent(NT_DOMAIN_ACCOUNT, nt_info);
lsa_free_info(&info);
@@ -534,6 +538,9 @@
if (lsa_enum_trusted_domains(server, domain, &info)
== NT_STATUS_SUCCESS) {
lsa_trusted_domainlist_t *list = &info.i_domain.di_trust;
+
+ nt_domain_flush(NT_DOMAIN_TRUSTED);
+
for (i = 0; i < list->t_num; i++) {
nt_info = &list->t_domains[i];
smb_domain_update_tabent(NT_DOMAIN_TRUSTED, nt_info);
@@ -549,7 +556,7 @@
smb_domain_update_tabent(int domain_type, lsa_nt_domaininfo_t *info)
{
nt_domain_t *entry;
- nt_domain_flush(domain_type);
+
entry = nt_domain_new(domain_type, info->n_domain, info->n_sid);
(void) nt_domain_add(entry);
}
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c Sun Feb 01 19:44:54 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.
*/
@@ -80,7 +80,7 @@
static DWORD lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *,
ndr_xa_t *);
static int lsarpc_s_UpdateDomainTable(ndr_xa_t *,
- smb_userinfo_t *, struct mslsa_domain_table *, DWORD *);
+ smb_account_t *, struct mslsa_domain_table *, DWORD *);
static ndr_stub_table_t lsarpc_stub_table[] = {
{ lsarpc_s_CloseHandle, LSARPC_OPNUM_CloseHandle },
@@ -680,11 +680,11 @@
{
struct mslsa_LookupNames *param = arg;
struct mslsa_rid_entry *rids;
- smb_userinfo_t *user_info = 0;
struct mslsa_domain_table *domain_table;
struct mslsa_domain_entry *domain_entry;
- DWORD status = NT_STATUS_SUCCESS;
- char *account;
+ smb_account_t account;
+ uint32_t status;
+ char *accname;
int rc = 0;
if (param->name_table->n_entry != 1)
@@ -693,24 +693,26 @@
rids = NDR_NEW(mxa, struct mslsa_rid_entry);
domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
- user_info = mlsvc_alloc_user_info();
- if (rids == NULL || domain_table == NULL ||
- domain_entry == NULL || user_info == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto name_lookup_failed;
+ if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
+ bzero(param, sizeof (struct mslsa_LookupNames));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
}
- account = (char *)param->name_table->names->str;
- status = lsa_lookup_name(account, SidTypeUnknown, user_info);
- if (status != NT_STATUS_SUCCESS)
- goto name_lookup_failed;
+ accname = (char *)param->name_table->names->str;
+ status = lsa_lookup_name(accname, SidTypeUnknown, &account);
+ if (status != NT_STATUS_SUCCESS) {
+ bzero(param, sizeof (struct mslsa_LookupNames));
+ param->status = NT_SC_ERROR(status);
+ return (NDR_DRC_OK);
+ }
/*
* Set up the rid table.
*/
- rids[0].sid_name_use = user_info->sid_name_use;
- rids[0].rid = user_info->rid;
+ rids[0].sid_name_use = account.a_type;
+ rids[0].rid = account.a_rid;
rids[0].domain_index = 0;
param->translated_sids.n_entry = 1;
param->translated_sids.rids = rids;
@@ -722,27 +724,23 @@
domain_table->n_entry = 1;
domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
- rc = NDR_MSTRING(mxa, user_info->domain_name,
+ rc = NDR_MSTRING(mxa, account.a_domain,
(ndr_mstring_t *)&domain_entry->domain_name);
domain_entry->domain_sid =
- (struct mslsa_sid *)NDR_SIDDUP(mxa, user_info->domain_sid);
+ (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
if (rc == -1 || domain_entry->domain_sid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto name_lookup_failed;
+ smb_account_free(&account);
+ bzero(param, sizeof (struct mslsa_LookupNames));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
}
param->domain_table = domain_table;
param->mapped_count = 1;
- param->status = 0;
-
- mlsvc_free_user_info(user_info);
- return (NDR_DRC_OK);
+ param->status = NT_STATUS_SUCCESS;
-name_lookup_failed:
- mlsvc_free_user_info(user_info);
- bzero(param, sizeof (struct mslsa_LookupNames));
- param->status = NT_SC_ERROR(status);
+ smb_account_free(&account);
return (NDR_DRC_OK);
}
@@ -767,22 +765,19 @@
struct mslsa_domain_entry *domain_entry;
struct mslsa_name_entry *names;
struct mslsa_name_entry *name;
- smb_userinfo_t *user_info;
+ smb_account_t account;
smb_sid_t *sid;
DWORD n_entry;
int result;
int i;
- user_info = mlsvc_alloc_user_info();
-
n_entry = param->lup_sid_table.n_entry;
names = NDR_NEWN(mxa, struct mslsa_name_entry, n_entry);
domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
MLSVC_DOMAIN_MAX);
- if (names == NULL || domain_table == NULL ||
- domain_entry == NULL || user_info == NULL) {
+ if (names == NULL || domain_table == NULL || domain_entry == NULL) {
bzero(param, sizeof (struct mslsa_LookupSids));
param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
return (NDR_DRC_OK);
@@ -797,18 +792,18 @@
bzero(&names[i], sizeof (struct mslsa_name_entry));
sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
- result = lsa_lookup_sid(sid, user_info);
+ result = lsa_lookup_sid(sid, &account);
if (result != NT_STATUS_SUCCESS)
goto lookup_sid_failed;
- if (NDR_MSTRING(mxa, user_info->name,
+ if (NDR_MSTRING(mxa, account.a_name,
(ndr_mstring_t *)&name->name) == -1) {
result = NT_STATUS_NO_MEMORY;
goto lookup_sid_failed;
}
- name->sid_name_use = user_info->sid_name_use;
+ name->sid_name_use = account.a_type;
- result = lsarpc_s_UpdateDomainTable(mxa, user_info,
+ result = lsarpc_s_UpdateDomainTable(mxa, &account,
domain_table, &name->domain_ix);
if (result == -1) {
@@ -816,7 +811,7 @@
goto lookup_sid_failed;
}
- mlsvc_release_user_info(user_info);
+ smb_account_free(&account);
}
param->domain_table = domain_table;
@@ -825,7 +820,6 @@
param->mapped_count = n_entry;
param->status = 0;
- mlsvc_free_user_info(user_info);
return (NDR_DRC_OK);
lookup_sid_failed:
@@ -835,7 +829,7 @@
param->mapped_count = 0;
param->status = NT_SC_ERROR(result);
- mlsvc_free_user_info(user_info);
+ smb_account_free(&account);
return (NDR_DRC_OK);
}
@@ -850,7 +844,7 @@
*/
static int
lsarpc_s_UpdateDomainTable(ndr_xa_t *mxa,
- smb_userinfo_t *user_info, struct mslsa_domain_table *domain_table,
+ smb_account_t *account, struct mslsa_domain_table *domain_table,
DWORD *domain_idx)
{
struct mslsa_domain_entry *dentry;
@@ -858,8 +852,8 @@
DWORD i;
int rc;
- if (user_info->sid_name_use == SidTypeUnknown ||
- user_info->sid_name_use == SidTypeInvalid) {
+ if (account->a_type == SidTypeUnknown ||
+ account->a_type == SidTypeInvalid) {
/*
* These types don't need to reference an entry in the
* domain table. So return -1.
@@ -876,7 +870,7 @@
for (i = 0; i < n_entry; ++i) {
if (smb_sid_cmp((smb_sid_t *)dentry[i].domain_sid,
- user_info->domain_sid)) {
+ account->a_domsid)) {
*domain_idx = i;
return (0);
}
@@ -885,10 +879,10 @@
if (i == MLSVC_DOMAIN_MAX)
return (-1);
- rc = NDR_MSTRING(mxa, user_info->domain_name,
+ rc = NDR_MSTRING(mxa, account->a_domain,
(ndr_mstring_t *)&dentry[i].domain_name);
dentry[i].domain_sid =
- (struct mslsa_sid *)NDR_SIDDUP(mxa, user_info->domain_sid);
+ (struct mslsa_sid *)NDR_SIDDUP(mxa, account->a_domsid);
if (rc == -1 || dentry[i].domain_sid == NULL)
return (-1);
@@ -912,22 +906,19 @@
struct lsar_name_entry2 *name;
struct mslsa_domain_table *domain_table;
struct mslsa_domain_entry *domain_entry;
- smb_userinfo_t *user_info;
+ smb_account_t account;
smb_sid_t *sid;
DWORD n_entry;
int result;
int i;
- user_info = mlsvc_alloc_user_info();
-
n_entry = param->lup_sid_table.n_entry;
names = NDR_NEWN(mxa, struct lsar_name_entry2, n_entry);
domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
domain_entry = NDR_NEWN(mxa, struct mslsa_domain_entry,
MLSVC_DOMAIN_MAX);
- if (names == NULL || domain_table == NULL ||
- domain_entry == NULL || user_info == NULL) {
+ if (names == NULL || domain_table == NULL || domain_entry == NULL) {
bzero(param, sizeof (struct lsar_lookup_sids2));
param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
return (NDR_DRC_OK);
@@ -942,18 +933,18 @@
bzero(name, sizeof (struct lsar_name_entry2));
sid = (smb_sid_t *)param->lup_sid_table.entries[i].psid;
- result = lsa_lookup_sid(sid, user_info);
+ result = lsa_lookup_sid(sid, &account);
if (result != NT_STATUS_SUCCESS)
goto lookup_sid_failed;
- if (NDR_MSTRING(mxa, user_info->name,
+ if (NDR_MSTRING(mxa, account.a_name,
(ndr_mstring_t *)&name->name) == -1) {
result = NT_STATUS_NO_MEMORY;
goto lookup_sid_failed;
}
- name->sid_name_use = user_info->sid_name_use;
+ name->sid_name_use = account.a_type;
- result = lsarpc_s_UpdateDomainTable(mxa, user_info,
+ result = lsarpc_s_UpdateDomainTable(mxa, &account,
domain_table, &name->domain_ix);
if (result == -1) {
@@ -961,7 +952,7 @@
goto lookup_sid_failed;
}
- mlsvc_release_user_info(user_info);
+ smb_account_free(&account);
}
param->domain_table = domain_table;
@@ -970,7 +961,6 @@
param->mapped_count = n_entry;
param->status = 0;
- mlsvc_free_user_info(user_info);
return (NDR_DRC_OK);
lookup_sid_failed:
@@ -980,7 +970,7 @@
param->mapped_count = 0;
param->status = NT_SC_ERROR(result);
- mlsvc_free_user_info(user_info);
+ smb_account_free(&account);
return (NDR_DRC_OK);
}
@@ -995,11 +985,11 @@
{
struct lsar_LookupNames2 *param = arg;
struct lsar_rid_entry2 *rids;
- smb_userinfo_t *user_info = 0;
struct mslsa_domain_table *domain_table;
struct mslsa_domain_entry *domain_entry;
- char *account;
- DWORD status = NT_STATUS_SUCCESS;
+ smb_account_t account;
+ uint32_t status;
+ char *accname;
int rc = 0;
if (param->name_table->n_entry != 1)
@@ -1008,25 +998,27 @@
rids = NDR_NEW(mxa, struct lsar_rid_entry2);
domain_table = NDR_NEW(mxa, struct mslsa_domain_table);
domain_entry = NDR_NEW(mxa, struct mslsa_domain_entry);
- user_info = mlsvc_alloc_user_info();
- if (rids == 0 || domain_table == 0 ||
- domain_entry == 0 || user_info == 0) {
- status = NT_STATUS_NO_MEMORY;
- goto name_lookup2_failed;
+ if (rids == NULL || domain_table == NULL || domain_entry == NULL) {
+ bzero(param, sizeof (struct lsar_LookupNames2));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
}
- account = (char *)param->name_table->names->str;
- status = lsa_lookup_name(account, SidTypeUnknown, user_info);
- if (status != NT_STATUS_SUCCESS)
- goto name_lookup2_failed;
+ accname = (char *)param->name_table->names->str;
+ status = lsa_lookup_name(accname, SidTypeUnknown, &account);
+ if (status != NT_STATUS_SUCCESS) {
+ bzero(param, sizeof (struct lsar_LookupNames2));
+ param->status = NT_SC_ERROR(status);
+ return (NDR_DRC_OK);
+ }
/*
* Set up the rid table.
*/
bzero(rids, sizeof (struct lsar_rid_entry2));
- rids[0].sid_name_use = user_info->sid_name_use;
- rids[0].rid = user_info->rid;
+ rids[0].sid_name_use = account.a_type;
+ rids[0].rid = account.a_rid;
rids[0].domain_index = 0;
param->translated_sids.n_entry = 1;
param->translated_sids.rids = rids;
@@ -1038,28 +1030,24 @@
domain_table->n_entry = 1;
domain_table->max_n_entry = MLSVC_DOMAIN_MAX;
- rc = NDR_MSTRING(mxa, user_info->domain_name,
+ rc = NDR_MSTRING(mxa, account.a_domain,
(ndr_mstring_t *)&domain_entry->domain_name);
domain_entry->domain_sid =
- (struct mslsa_sid *)NDR_SIDDUP(mxa, user_info->domain_sid);
+ (struct mslsa_sid *)NDR_SIDDUP(mxa, account.a_domsid);
if (rc == -1 || domain_entry->domain_sid == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto name_lookup2_failed;
+ smb_account_free(&account);
+ bzero(param, sizeof (struct lsar_LookupNames2));
+ param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
+ return (NDR_DRC_OK);
}
param->domain_table = domain_table;
param->mapped_count = 1;
- param->status = 0;
-
- mlsvc_free_user_info(user_info);
- return (NDR_DRC_OK);
+ param->status = NT_STATUS_SUCCESS;
-name_lookup2_failed:
- mlsvc_free_user_info(user_info);
- bzero(param, sizeof (struct lsar_LookupNames2));
- param->status = NT_SC_ERROR(status);
+ smb_account_free(&account);
return (NDR_DRC_OK);
}
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c Sun Feb 01 19:44:54 2009 -0700
@@ -31,8 +31,6 @@
#include <unistd.h>
#include <netdb.h>
#include <assert.h>
-#include <pwd.h>
-#include <grp.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlrpc.h>
@@ -270,20 +268,19 @@
(void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN);
if (smb_ishostname(domain_name)) {
- sid = smb_sid_dup(nt_domain_local_sid());
- } else if (strcasecmp(resource_domain, domain_name) == 0) {
+ sid = nt_domain_local_sid();
+ } else if (utf8_strcasecmp(resource_domain, domain_name) == 0) {
/*
* We should not be asked to provide
* the domain SID for the primary domain.
*/
sid = NULL;
} else {
- sid = smb_wka_lookup_name(domain_name, 0);
+ sid = smb_wka_get_sid(domain_name);
}
if (sid) {
param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, sid);
- free(sid);
if (param->sid == NULL) {
bzero(param, sizeof (struct samr_LookupDomain));
@@ -465,15 +462,15 @@
case NT_DOMAIN_BUILTIN:
domain = "BUILTIN";
user_cnt = 0;
- rc = smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &alias_cnt);
+ alias_cnt = smb_sam_grp_cnt(data->kd_type);
break;
case NT_DOMAIN_LOCAL:
rc = smb_getnetbiosname(hostname, sizeof (hostname));
if (rc == 0) {
domain = hostname;
- user_cnt = smb_pwd_num();
- rc = smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &alias_cnt);
+ user_cnt = smb_sam_usr_cnt();
+ alias_cnt = smb_sam_grp_cnt(data->kd_type);
}
break;
@@ -535,11 +532,11 @@
}
/*
- * samr_s_LookupNames
+ * Looks up the given name in the specified domain which could
+ * be either the built-in or local domain.
*
- * The definition for this interface is obviously wrong but I can't
- * seem to get it to work the way I think it should. It should
- * support multiple name lookup but I can only get one working for now.
+ * CAVEAT: this function should be able to handle a list of
+ * names but currently it can only handle one name at a time.
*/
static int
samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
@@ -548,12 +545,9 @@
ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
ndr_handle_t *hd;
samr_keydata_t *data;
+ smb_account_t account;
smb_wka_t *wka;
- smb_group_t grp;
- smb_passwd_t smbpw;
- smb_sid_t *sid;
uint32_t status = NT_STATUS_SUCCESS;
- int rc;
if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
status = NT_STATUS_INVALID_HANDLE;
@@ -582,7 +576,7 @@
switch (data->kd_type) {
case NT_DOMAIN_BUILTIN:
- wka = smb_wka_lookup((char *)param->name.str);
+ wka = smb_wka_lookup_name((char *)param->name.str);
if (wka != NULL) {
param->rids.n_entry = 1;
(void) smb_sid_getrid(wka->wka_binsid,
@@ -595,30 +589,17 @@
break;
case NT_DOMAIN_LOCAL:
- rc = smb_lgrp_getbyname((char *)param->name.str, &grp);
- if (rc == SMB_LGRP_SUCCESS) {
+ status = smb_sam_lookup_name(NULL, (char *)param->name.str,
+ SidTypeUnknown, &account);
+ if (status == NT_STATUS_SUCCESS) {
param->rids.n_entry = 1;
- param->rids.rid[0] = grp.sg_rid;
+ param->rids.rid[0] = account.a_rid;
param->rid_types.n_entry = 1;
- param->rid_types.rid_type[0] = grp.sg_id.gs_type;
+ param->rid_types.rid_type[0] = account.a_type;
param->status = NT_STATUS_SUCCESS;
- smb_lgrp_free(&grp);
+ smb_account_free(&account);
return (NDR_DRC_OK);
}
-
- if (smb_pwd_getpwnam((const char *)param->name.str, &smbpw)
- != NULL) {
- if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER,
- &sid) == IDMAP_SUCCESS) {
- param->rids.n_entry = 1;
- (void) smb_sid_getrid(sid, ¶m->rids.rid[0]);
- param->rid_types.n_entry = 1;
- param->rid_types.rid_type[0] = SidTypeUser;
- param->status = NT_STATUS_SUCCESS;
- free(sid);
- return (NDR_DRC_OK);
- }
- }
break;
default:
@@ -728,7 +709,6 @@
ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle;
ndr_handle_t *hd;
samr_keydata_t *data;
- smb_wka_t *wka;
smb_sid_t *user_sid = NULL;
smb_sid_t *dom_sid;
smb_group_t grp;
@@ -745,12 +725,10 @@
data = (samr_keydata_t *)hd->nh_data;
switch (data->kd_type) {
case NT_DOMAIN_BUILTIN:
- wka = smb_wka_lookup("builtin");
- if (wka == NULL) {
+ if ((dom_sid = smb_wka_get_sid("builtin")) == NULL) {
status = NT_STATUS_INTERNAL_ERROR;
goto query_error;
}
- dom_sid = wka->wka_binsid;
break;
case NT_DOMAIN_LOCAL:
dom_sid = nt_domain_local_sid();
@@ -973,8 +951,9 @@
smb_pwditer_t pwi;
smb_luser_t *uinfo;
int num_users;
- int start_idx, idx;
- int ret_cnt;
+ int start_idx;
+ int max_retcnt, retcnt;
+ int skip;
if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
status = NT_STATUS_INVALID_HANDLE;
@@ -998,34 +977,37 @@
goto no_info;
case NT_DOMAIN_LOCAL:
- num_users = smb_pwd_num();
+ num_users = smb_sam_usr_cnt();
start_idx = param->start_idx;
if ((num_users == 0) || (start_idx >= num_users))
goto no_info;
- ret_cnt = num_users - start_idx;
- if (ret_cnt > param->max_entries)
- ret_cnt = param->max_entries;
+ max_retcnt = num_users - start_idx;
+ if (max_retcnt > param->max_entries)
+ max_retcnt = param->max_entries;
param->users.acct = NDR_MALLOC(mxa,
- ret_cnt * sizeof (struct user_acct_info));
+ max_retcnt * sizeof (struct user_acct_info));
user = param->users.acct;
if (user == NULL) {
status = NT_STATUS_NO_MEMORY;
goto error;
}
- bzero(user, ret_cnt * sizeof (struct user_acct_info));
+ bzero(user, max_retcnt * sizeof (struct user_acct_info));
- ret_cnt = idx = 0;
if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
goto no_info;
+ skip = retcnt = 0;
while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
- if (idx++ < start_idx)
+ if (skip++ < start_idx)
continue;
+ if (retcnt++ >= max_retcnt)
+ break;
+
assert(uinfo->su_name != NULL);
- user->index = start_idx + ret_cnt + 1;
+ user->index = start_idx + retcnt;
user->rid = uinfo->su_rid;
user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
if (uinfo->su_ctrl & SMB_PWF_DISABLE)
@@ -1041,17 +1023,21 @@
(void) NDR_MSTRING(mxa, uinfo->su_desc,
(ndr_mstring_t *)&user->desc);
user++;
- ret_cnt++;
}
smb_pwd_iterclose(&pwi);
+ if (retcnt >= max_retcnt) {
+ retcnt = max_retcnt;
+ param->status = status;
+ } else {
+ param->status = ERROR_MORE_ENTRIES;
+ }
+
param->users.total_size = num_users;
- param->users.returned_size = ret_cnt;
+ param->users.returned_size = retcnt;
param->users.switch_value = param->level;
- param->users.count = ret_cnt;
+ param->users.count = retcnt;
- if (ret_cnt < (num_users - start_idx))
- param->status = ERROR_MORE_ENTRIES;
break;
default:
@@ -1059,7 +1045,6 @@
goto error;
}
- param->status = status;
return (NDR_DRC_OK);
no_info:
@@ -1422,7 +1407,7 @@
data = (samr_keydata_t *)hd->nh_data;
- (void) smb_lgrp_numbydomain((smb_gdomain_t)data->kd_type, &cnt);
+ cnt = smb_sam_grp_cnt(data->kd_type);
if (cnt <= param->resume_handle) {
param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
sizeof (struct aliases_info));
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c Sun Feb 01 19:44:54 2009 -0700
@@ -62,22 +62,19 @@
* call free when it is no longer required.
*/
uint32_t
-mlsvc_lookup_name(char *account, smb_sid_t **sid, uint16_t *sid_type)
+mlsvc_lookup_name(char *name, smb_sid_t **sid, uint16_t *sid_type)
{
- smb_userinfo_t *ainfo;
+ smb_account_t account;
uint32_t status;
- if ((ainfo = mlsvc_alloc_user_info()) == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- status = lsa_lookup_name(account, *sid_type, ainfo);
+ status = lsa_lookup_name(name, *sid_type, &account);
if (status == NT_STATUS_SUCCESS) {
- *sid = ainfo->user_sid;
- ainfo->user_sid = NULL;
- *sid_type = ainfo->sid_name_use;
+ *sid = account.a_sid;
+ account.a_sid = NULL;
+ *sid_type = account.a_type;
+ smb_account_free(&account);
}
- mlsvc_free_user_info(ainfo);
return (status);
}
@@ -92,134 +89,24 @@
uint32_t
mlsvc_lookup_sid(smb_sid_t *sid, char **name)
{
- smb_userinfo_t *ainfo;
+ smb_account_t ainfo;
uint32_t status;
int namelen;
- if ((ainfo = mlsvc_alloc_user_info()) == NULL)
- return (NT_STATUS_NO_MEMORY);
+ if ((status = lsa_lookup_sid(sid, &ainfo)) == NT_STATUS_SUCCESS) {
+ namelen = strlen(ainfo.a_domain) + strlen(ainfo.a_name) + 2;
+ if ((*name = malloc(namelen)) != NULL)
+ (void) snprintf(*name, namelen, "%s\\%s",
+ ainfo.a_domain, ainfo.a_name);
+ else
+ status = NT_STATUS_NO_MEMORY;
- status = lsa_lookup_sid(sid, ainfo);
- if (status == NT_STATUS_SUCCESS) {
- namelen = strlen(ainfo->domain_name) + strlen(ainfo->name) + 2;
- if ((*name = malloc(namelen)) == NULL) {
- mlsvc_free_user_info(ainfo);
- return (NT_STATUS_NO_MEMORY);
- }
- (void) snprintf(*name, namelen, "%s\\%s",
- ainfo->domain_name, ainfo->name);
+ smb_account_free(&ainfo);
}
- mlsvc_free_user_info(ainfo);
return (status);
}
-/*
- * mlsvc_alloc_user_info
- *
- * Allocate a user_info structure and set the contents to zero. A
- * pointer to the user_info structure is returned.
- */
-smb_userinfo_t *
-mlsvc_alloc_user_info(void)
-{
- smb_userinfo_t *user_info;
-
- user_info = (smb_userinfo_t *)malloc(sizeof (smb_userinfo_t));
- if (user_info == NULL)
- return (NULL);
-
- bzero(user_info, sizeof (smb_userinfo_t));
- return (user_info);
-}
-
-/*
- * mlsvc_free_user_info
- *
- * Free a user_info structure. This function ensures that the contents
- * of the user_info are freed as well as the user_info itself.
- */
-void
-mlsvc_free_user_info(smb_userinfo_t *user_info)
-{
- if (user_info) {
- mlsvc_release_user_info(user_info);
- free(user_info);
- }
-}
-
-/*
- * mlsvc_release_user_info
- *
- * Release the contents of a user_info structure and zero out the
- * elements but do not free the user_info structure itself. This
- * function cleans out the structure so that it can be reused without
- * worrying about stale contents.
- */
-void
-mlsvc_release_user_info(smb_userinfo_t *user_info)
-{
- int i;
-
- if (user_info == NULL)
- return;
-
- free(user_info->name);
- free(user_info->domain_sid);
- free(user_info->domain_name);
- free(user_info->groups);
-
- if (user_info->n_other_grps) {
- for (i = 0; i < user_info->n_other_grps; i++)
- free(user_info->other_grps[i].sid);
-
- free(user_info->other_grps);
- }
-
- free(user_info->session_key);
- free(user_info->user_sid);
- free(user_info->pgrp_sid);
- bzero(user_info, sizeof (smb_userinfo_t));
-}
-
-/*
- * mlsvc_setadmin_user_info
- *
- * Determines if the given user is the domain Administrator or a
- * member of Domain Admins or Administrators group and set the
- * user_info->flags accordingly.
- */
-void
-mlsvc_setadmin_user_info(smb_userinfo_t *user_info)
-{
- nt_domain_t *domain;
- smb_group_t grp;
- int rc, i;
-
- if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL)
- return;
-
- if (!smb_sid_cmp((smb_sid_t *)user_info->domain_sid, domain->sid))
- return;
-
- if (user_info->rid == DOMAIN_USER_RID_ADMIN)
- user_info->flags |= SMB_UINFO_FLAG_DADMIN;
- else if (user_info->primary_group_rid == DOMAIN_GROUP_RID_ADMINS)
- user_info->flags |= SMB_UINFO_FLAG_DADMIN;
- else {
- for (i = 0; i < user_info->n_groups; i++)
- if (user_info->groups[i].rid == DOMAIN_GROUP_RID_ADMINS)
- user_info->flags |= SMB_UINFO_FLAG_DADMIN;
- }
-
- rc = smb_lgrp_getbyname("Administrators", &grp);
- if (rc == SMB_LGRP_SUCCESS) {
- if (smb_lgrp_is_member(&grp, user_info->user_sid))
- user_info->flags |= SMB_UINFO_FLAG_LADMIN;
- smb_lgrp_free(&grp);
- }
-}
-
DWORD
mlsvc_netlogon(char *server, char *domain)
{
--- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c Sun Feb 01 19:44:54 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.
*/
@@ -47,9 +47,9 @@
#include <smbsrv/smb_token.h>
#include <mlsvc.h>
-static DWORD netlogon_logon_private(netr_client_t *, smb_userinfo_t *);
-static DWORD netr_server_samlogon(mlsvc_handle_t *, netr_info_t *, char *,
- netr_client_t *, smb_userinfo_t *);
+static uint32_t netlogon_logon_private(netr_client_t *, smb_token_t *);
+static uint32_t netr_server_samlogon(mlsvc_handle_t *, netr_info_t *, char *,
+ netr_client_t *, smb_token_t *);
static void netr_invalidate_chain(void);
static void netr_interactive_samlogon(netr_info_t *, netr_client_t *,
struct netr_logon_info1 *);
@@ -57,6 +57,11 @@
netr_client_t *, struct netr_logon_info2 *);
static void netr_setup_identity(ndr_heap_t *, netr_client_t *,
netr_logon_id_t *);
+static boolean_t netr_isadmin(struct netr_validation_info3 *);
+static uint32_t netr_setup_domain_groups(struct netr_validation_info3 *,
+ smb_ids_t *);
+static uint32_t netr_setup_token_wingrps(struct netr_validation_info3 *,
+ smb_token_t *);
/*
* Shared with netr_auth.c
@@ -80,27 +85,27 @@
* NT status will be returned, in which case the token contents will
* be invalid.
*/
-DWORD
-netlogon_logon(netr_client_t *clnt, smb_userinfo_t *user_info)
+uint32_t
+netlogon_logon(netr_client_t *clnt, smb_token_t *token)
{
- DWORD status;
+ uint32_t status;
(void) mutex_lock(&netlogon_logon_mutex);
- status = netlogon_logon_private(clnt, user_info);
+ status = netlogon_logon_private(clnt, token);
(void) mutex_unlock(&netlogon_logon_mutex);
return (status);
}
-static DWORD
-netlogon_logon_private(netr_client_t *clnt, smb_userinfo_t *user_info)
+static uint32_t
+netlogon_logon_private(netr_client_t *clnt, smb_token_t *token)
{
char resource_domain[SMB_PI_MAX_DOMAIN];
char server[NETBIOS_NAME_SZ * 2];
mlsvc_handle_t netr_handle;
smb_domain_t di;
- DWORD status;
+ uint32_t status;
int retries = 0, server_changed = 0;
(void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN);
@@ -144,7 +149,7 @@
}
status = netr_server_samlogon(&netr_handle,
- &netr_global_info, di.d_dc, clnt, user_info);
+ &netr_global_info, di.d_dc, clnt, token);
(void) netr_close(&netr_handle);
} while (status == NT_STATUS_INSUFFICIENT_LOGON_INFO && retries++ < 3);
@@ -155,75 +160,51 @@
return (status);
}
-static DWORD
-netr_setup_userinfo(struct netr_validation_info3 *info3,
- smb_userinfo_t *user_info, netr_client_t *clnt, netr_info_t *netr_info)
+static uint32_t
+netr_setup_token(struct netr_validation_info3 *info3, netr_client_t *clnt,
+ netr_info_t *netr_info, smb_token_t *token)
{
- smb_sid_attrs_t *other_grps;
char *username, *domain;
- int i, nbytes;
unsigned char rc4key[SMBAUTH_SESSION_KEY_SZ];
+ smb_sid_t *domsid;
+ uint32_t status;
+ char nbdomain[NETBIOS_NAME_SZ];
- user_info->sid_name_use = SidTypeUser;
- user_info->rid = info3->UserId;
- user_info->primary_group_rid = info3->PrimaryGroupId;
- user_info->domain_sid = smb_sid_dup((smb_sid_t *)info3->LogonDomainId);
+ domsid = (smb_sid_t *)info3->LogonDomainId;
- if (user_info->domain_sid == NULL)
+ token->tkn_user.i_sid = smb_sid_splice(domsid, info3->UserId);
+ if (token->tkn_user.i_sid == NULL)
return (NT_STATUS_NO_MEMORY);
- user_info->user_sid = smb_sid_splice(user_info->domain_sid,
- user_info->rid);
- if (user_info->user_sid == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- user_info->pgrp_sid = smb_sid_splice(user_info->domain_sid,
- user_info->primary_group_rid);
- if (user_info->pgrp_sid == NULL)
+ token->tkn_primary_grp.i_sid = smb_sid_splice(domsid,
+ info3->PrimaryGroupId);
+ if (token->tkn_primary_grp.i_sid == NULL)
return (NT_STATUS_NO_MEMORY);
username = (info3->EffectiveName.str)
- ? (char *)info3->EffectiveName.str : clnt->username;
- domain = (info3->LogonDomainName.str)
- ? (char *)info3->LogonDomainName.str : clnt->domain;
+ ? (char *)info3->EffectiveName.str : clnt->real_username;
+
+ if (info3->LogonDomainName.str) {
+ domain = (char *)info3->LogonDomainName.str;
+ } else if (*clnt->real_domain != '\0') {
+ domain = clnt->real_domain;
+ } else {
+ (void) smb_getdomainname(nbdomain, sizeof (nbdomain));
+ domain = nbdomain;
+ }
if (username)
- user_info->name = strdup(username);
+ token->tkn_account_name = strdup(username);
if (domain)
- user_info->domain_name = strdup(domain);
+ token->tkn_domain_name = strdup(domain);
- if (user_info->name == NULL || user_info->domain_name == NULL)
+ if (token->tkn_account_name == NULL || token->tkn_domain_name == NULL)
return (NT_STATUS_NO_MEMORY);
- nbytes = info3->GroupCount * sizeof (smb_rid_attrs_t);
- if (nbytes) {
- if ((user_info->groups = malloc(nbytes)) != NULL) {
- user_info->n_groups = info3->GroupCount;
- (void) memcpy(user_info->groups,
- info3->GroupIds, nbytes);
- } else {
- return (NT_STATUS_NO_MEMORY);
- }
- }
- nbytes = info3->SidCount * sizeof (smb_sid_attrs_t);
- if (nbytes) {
- if ((other_grps = malloc(nbytes)) != NULL) {
- user_info->other_grps = other_grps;
- for (i = 0; i < info3->SidCount; i++) {
- other_grps[i].attrs =
- info3->ExtraSids[i].attributes;
+ status = netr_setup_token_wingrps(info3, token);
+ if (status != NT_STATUS_SUCCESS)
+ return (status);
- other_grps[i].sid = smb_sid_dup(
- (smb_sid_t *)info3->ExtraSids[i].sid);
-
- if (other_grps[i].sid == NULL)
- break;
- }
- user_info->n_other_grps = i;
- } else {
- return (NT_STATUS_NO_MEMORY);
- }
- }
/*
* The UserSessionKey in NetrSamLogon RPC is obfuscated using the
* session key obtained in the NETLOGON credential chain.
@@ -232,15 +213,15 @@
* exclusively ored with the 16 byte UserSessionKey to recover
* the the clear form.
*/
- if ((user_info->session_key = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
+ if ((token->tkn_session_key = malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
return (NT_STATUS_NO_MEMORY);
bzero(rc4key, SMBAUTH_SESSION_KEY_SZ);
bcopy(netr_info->session_key.key, rc4key, netr_info->session_key.len);
- bcopy(info3->UserSessionKey.data, user_info->session_key,
+ bcopy(info3->UserSessionKey.data, token->tkn_session_key,
SMBAUTH_SESSION_KEY_SZ);
- rand_hash((unsigned char *)user_info->session_key,
+ rand_hash((unsigned char *)token->tkn_session_key,
SMBAUTH_SESSION_KEY_SZ, rc4key, SMBAUTH_SESSION_KEY_SZ);
- mlsvc_setadmin_user_info(user_info);
+
return (NT_STATUS_SUCCESS);
}
@@ -268,9 +249,9 @@
* NT_STATUS_PASSWORD_EXPIRED
* NT_STATUS_ACCOUNT_DISABLED
*/
-DWORD
+uint32_t
netr_server_samlogon(mlsvc_handle_t *netr_handle, netr_info_t *netr_info,
- char *server, netr_client_t *clnt, smb_userinfo_t *user_info)
+ char *server, netr_client_t *clnt, smb_token_t *token)
{
struct netr_SamLogon arg;
struct netr_authenticator auth;
@@ -281,7 +262,7 @@
ndr_heap_t *heap;
int opnum;
int rc, len;
- DWORD status;
+ uint32_t status;
bzero(&arg, sizeof (struct netr_SamLogon));
opnum = NETR_OPNUM_SamLogon;
@@ -359,7 +340,7 @@
}
info3 = arg.ru.info3;
- status = netr_setup_userinfo(info3, user_info, clnt, netr_info);
+ status = netr_setup_token(info3, clnt, netr_info, token);
}
ndr_rpc_release(netr_handle);
@@ -476,7 +457,7 @@
*
* Generate the new seed for the credential chain. The new seed is
* formed by adding (timestamp + 1) to the current client credential.
- * The only quirk is the DWORD style addition.
+ * The only quirk is the uint32_t style addition.
*
* Returns NT_STATUS_INSUFFICIENT_LOGON_INFO if auth->credential is a
* NULL pointer. The Authenticator field of the SamLogon response packet
@@ -487,12 +468,12 @@
* Returns NT_STATUS_SUCCESS if the server returned a valid credential.
* Otherwise we retirm NT_STATUS_UNSUCCESSFUL.
*/
-DWORD
+uint32_t
netr_validate_chain(netr_info_t *netr_info, struct netr_authenticator *auth)
{
netr_cred_t cred;
- DWORD result = NT_STATUS_SUCCESS;
- DWORD *dwp;
+ uint32_t result = NT_STATUS_SUCCESS;
+ uint32_t *dwp;
++netr_info->timestamp;
@@ -523,7 +504,7 @@
* Otherwise generate the next step in the chain.
*/
/*LINTED E_BAD_PTR_CAST_ALIGN*/
- dwp = (DWORD *)&netr_info->client_credential;
+ dwp = (uint32_t *)&netr_info->client_credential;
dwp[0] += netr_info->timestamp;
netr_info->flags |= NETR_FLG_VALID;
@@ -589,3 +570,127 @@
ndr_heap_mkvcs(heap, clnt->workstation,
(ndr_vcstr_t *)&identity->workstation);
}
+
+/*
+ * Sets up domain, local and well-known group membership for the given
+ * token. Two assumptions have been made here:
+ *
+ * a) token already contains a valid user SID so that group
+ * memberships can be established
+ *
+ * b) token belongs to a domain user
+ */
+static uint32_t
+netr_setup_token_wingrps(struct netr_validation_info3 *info3,
+ smb_token_t *token)
+{
+ smb_ids_t tkn_grps;
+ uint32_t status;
+
+ tkn_grps.i_cnt = 0;
+ tkn_grps.i_ids = NULL;
+
+ status = netr_setup_domain_groups(info3, &tkn_grps);
+ if (status != NT_STATUS_SUCCESS) {
+ smb_ids_free(&tkn_grps);
+ return (status);
+ }
+
+ status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps);
+ if (status != NT_STATUS_SUCCESS) {
+ smb_ids_free(&tkn_grps);
+ return (status);
+ }
+
+ status = smb_wka_token_groups(netr_isadmin(info3), &tkn_grps);
+ if (status == NT_STATUS_SUCCESS)
+ token->tkn_win_grps = tkn_grps;
+ else
+ smb_ids_free(&tkn_grps);
+
+ return (status);
+}
+
+/*
+ * Converts groups information in the returned structure by domain controller
+ * (info3) to an internal representation (gids)
+ */
+static uint32_t
+netr_setup_domain_groups(struct netr_validation_info3 *info3, smb_ids_t *gids)
+{
+ smb_sid_t *domain_sid;
+ smb_id_t *ids;
+ int i, total_cnt;
+
+ if ((i = info3->GroupCount) == 0)
+ i++;
+ i += info3->SidCount;
+
+ total_cnt = gids->i_cnt + i;
+
+ gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
+ if (gids->i_ids == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ domain_sid = (smb_sid_t *)info3->LogonDomainId;
+
+ ids = gids->i_ids + gids->i_cnt;
+ for (i = 0; i < info3->GroupCount; i++, gids->i_cnt++, ids++) {
+ ids->i_sid = smb_sid_splice(domain_sid, info3->GroupIds[i].rid);
+ if (ids->i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ ids->i_attrs = info3->GroupIds[i].attributes;
+ }
+
+ if (info3->GroupCount == 0) {
+ /*
+ * if there's no global group should add the primary group.
+ */
+ ids->i_sid = smb_sid_splice(domain_sid, info3->PrimaryGroupId);
+ if (ids->i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ ids->i_attrs = 0x7;
+ gids->i_cnt++;
+ ids++;
+ }
+
+ /* Add the extra SIDs */
+ for (i = 0; i < info3->SidCount; i++, gids->i_cnt++, ids++) {
+ ids->i_sid = smb_sid_dup((smb_sid_t *)info3->ExtraSids[i].sid);
+ if (ids->i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ ids->i_attrs = info3->ExtraSids[i].attributes;
+ }
+
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * Determines if the given user is the domain Administrator or a
+ * member of Domain Admins
+ */
+static boolean_t
+netr_isadmin(struct netr_validation_info3 *info3)
+{
+ nt_domain_t *domain;
+ int i;
+
+ if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL)
+ return (B_FALSE);
+
+ if (!smb_sid_cmp((smb_sid_t *)info3->LogonDomainId, domain->sid))
+ return (B_FALSE);
+
+ if ((info3->UserId == DOMAIN_USER_RID_ADMIN) ||
+ (info3->PrimaryGroupId == DOMAIN_GROUP_RID_ADMINS))
+ return (B_TRUE);
+
+ for (i = 0; i < info3->GroupCount; i++)
+ if (info3->GroupIds[i].rid == DOMAIN_GROUP_RID_ADMINS)
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c Sun Feb 01 19:44:54 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.
*/
@@ -28,8 +28,6 @@
* functions.
*/
-#include <unistd.h>
-#include <netdb.h>
#include <alloca.h>
#include <smbsrv/libsmb.h>
@@ -48,9 +46,7 @@
#define SAM_KEYLEN 16
extern DWORD samr_set_user_info(mlsvc_handle_t *, smb_auth_info_t *);
-
-static struct samr_sid *sam_get_domain_sid(mlsvc_handle_t *, char *, char *,
- smb_userinfo_t *);
+static struct samr_sid *sam_get_domain_sid(mlsvc_handle_t *, char *, char *);
/*
* sam_create_trust_account
@@ -113,7 +109,6 @@
mlsvc_handle_t samr_handle;
mlsvc_handle_t domain_handle;
mlsvc_handle_t user_handle;
- smb_userinfo_t *user_info;
union samr_user_info sui;
struct samr_sid *sid;
DWORD rid;
@@ -121,9 +116,6 @@
int rc;
char *user = smbrdr_ipc_get_user();
- if ((user_info = mlsvc_alloc_user_info()) == 0)
- return (NT_STATUS_NO_MEMORY);
-
rc = samr_open(server, domain_name, user, SAM_CONNECT_CREATE_ACCOUNT,
&samr_handle);
@@ -131,11 +123,10 @@
status = NT_STATUS_OPEN_FAILED;
smb_tracef("SamCreateAccount[%s\\%s]: %s",
domain_name, account_name, xlate_nt_status(status));
- mlsvc_free_user_info(user_info);
return (status);
}
- sid = sam_get_domain_sid(&samr_handle, server, domain_name, user_info);
+ sid = sam_get_domain_sid(&samr_handle, server, domain_name);
status = samr_open_domain(&samr_handle,
SAM_DOMAIN_CREATE_ACCOUNT, sid, &domain_handle);
@@ -164,7 +155,6 @@
}
(void) samr_close_handle(&samr_handle);
- mlsvc_free_user_info(user_info);
free(sid);
return (status);
}
@@ -204,52 +194,41 @@
mlsvc_handle_t samr_handle;
mlsvc_handle_t domain_handle;
mlsvc_handle_t user_handle;
- smb_userinfo_t *user_info;
+ smb_account_t ainfo;
struct samr_sid *sid;
- DWORD rid;
DWORD access_mask;
DWORD status;
int rc;
char *user = smbrdr_ipc_get_user();
- if ((user_info = mlsvc_alloc_user_info()) == 0)
- return (NT_STATUS_NO_MEMORY);
-
rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
&samr_handle);
- if (rc != 0) {
- mlsvc_free_user_info(user_info);
+ if (rc != 0)
return (NT_STATUS_OPEN_FAILED);
+
+ sid = sam_get_domain_sid(&samr_handle, server, domain_name);
+ status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, sid,
+ &domain_handle);
+ free(sid);
+ if (status != NT_STATUS_SUCCESS) {
+ (void) samr_close_handle(&samr_handle);
+ return (status);
}
- sid = sam_get_domain_sid(&samr_handle, server, domain_name, user_info);
-
- status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION,
- sid, &domain_handle);
- if (status == 0) {
- mlsvc_release_user_info(user_info);
- status = samr_lookup_domain_names(&domain_handle,
- account_name, user_info);
-
- if (status == 0) {
- rid = user_info->rid;
- access_mask = STANDARD_RIGHTS_EXECUTE | DELETE;
-
- status = samr_open_user(&domain_handle, access_mask,
- rid, &user_handle);
- if (status == NT_STATUS_SUCCESS) {
- if (samr_delete_user(&user_handle) != 0)
- (void) samr_close_handle(&user_handle);
- }
+ status = samr_lookup_domain_names(&domain_handle, account_name, &ainfo);
+ if (status == NT_STATUS_SUCCESS) {
+ access_mask = STANDARD_RIGHTS_EXECUTE | DELETE;
+ status = samr_open_user(&domain_handle, access_mask,
+ ainfo.a_rid, &user_handle);
+ if (status == NT_STATUS_SUCCESS) {
+ if (samr_delete_user(&user_handle) != 0)
+ (void) samr_close_handle(&user_handle);
}
-
- (void) samr_close_handle(&domain_handle);
}
+ (void) samr_close_handle(&domain_handle);
(void) samr_close_handle(&samr_handle);
- mlsvc_free_user_info(user_info);
- free(sid);
return (status);
}
@@ -266,58 +245,46 @@
mlsvc_handle_t samr_handle;
mlsvc_handle_t domain_handle;
mlsvc_handle_t user_handle;
- smb_userinfo_t *user_info;
+ smb_account_t ainfo;
struct samr_sid *sid;
- DWORD rid;
DWORD access_mask;
DWORD status;
int rc;
char *user = smbrdr_ipc_get_user();
- if ((user_info = mlsvc_alloc_user_info()) == 0)
- return (NT_STATUS_NO_MEMORY);
-
rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
&samr_handle);
- if (rc != 0) {
- mlsvc_free_user_info(user_info);
+ if (rc != 0)
return (NT_STATUS_OPEN_FAILED);
- }
- sid = sam_get_domain_sid(&samr_handle, server, domain_name, user_info);
-
+ sid = sam_get_domain_sid(&samr_handle, server, domain_name);
status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, sid,
&domain_handle);
- if (status == 0) {
- mlsvc_release_user_info(user_info);
- status = samr_lookup_domain_names(&domain_handle, account_name,
- user_info);
-
- if (status == 0) {
- rid = user_info->rid;
-
- /*
- * Win2000 client uses this access mask. The
- * following SAMR user specific rights bits are
- * set: set password, set attributes, and get
- * attributes.
- */
-
- access_mask = 0xb0;
-
- status = samr_open_user(&domain_handle,
- access_mask, rid, &user_handle);
- if (status == NT_STATUS_SUCCESS)
- (void) samr_close_handle(&user_handle);
- }
-
- (void) samr_close_handle(&domain_handle);
+ free(sid);
+ if (status != NT_STATUS_SUCCESS) {
+ (void) samr_close_handle(&samr_handle);
+ return (status);
}
+ status = samr_lookup_domain_names(&domain_handle, account_name, &ainfo);
+ if (status == NT_STATUS_SUCCESS) {
+ /*
+ * Win2000 client uses this access mask. The
+ * following SAMR user specific rights bits are
+ * set: set password, set attributes, and get
+ * attributes.
+ */
+
+ access_mask = 0xb0;
+ status = samr_open_user(&domain_handle,
+ access_mask, ainfo.a_rid, &user_handle);
+ if (status == NT_STATUS_SUCCESS)
+ (void) samr_close_handle(&user_handle);
+ }
+
+ (void) samr_close_handle(&domain_handle);
(void) samr_close_handle(&samr_handle);
- mlsvc_free_user_info(user_info);
- free(sid);
return (status);
}
@@ -335,7 +302,7 @@
{
mlsvc_handle_t samr_handle;
mlsvc_handle_t domain_handle;
- smb_userinfo_t *user_info;
+ smb_account_t ainfo;
struct samr_sid *domain_sid;
int rc;
DWORD status;
@@ -343,45 +310,34 @@
*rid_ret = 0;
- if ((user_info = mlsvc_alloc_user_info()) == 0)
- return (NT_STATUS_NO_MEMORY);
-
rc = samr_open(server, domain_name, user, SAM_LOOKUP_INFORMATION,
&samr_handle);
- if (rc != 0) {
- mlsvc_free_user_info(user_info);
+ if (rc != 0)
return (NT_STATUS_OPEN_FAILED);
- }
- rc = samr_lookup_domain(&samr_handle, domain_name, user_info);
- if (rc != 0) {
+ domain_sid = (struct samr_sid *)samr_lookup_domain(&samr_handle,
+ domain_name);
+ if (domain_sid == NULL) {
(void) samr_close_handle(&samr_handle);
- mlsvc_free_user_info(user_info);
return (NT_STATUS_NO_SUCH_DOMAIN);
}
- domain_sid = (struct samr_sid *)user_info->domain_sid;
-
status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION,
domain_sid, &domain_handle);
- if (status == 0) {
- mlsvc_release_user_info(user_info);
-
+ if (status == NT_STATUS_SUCCESS) {
status = samr_lookup_domain_names(&domain_handle,
- account_name, user_info);
- if (status == 0)
- *rid_ret = user_info->rid;
+ account_name, &ainfo);
+ if (status == NT_STATUS_SUCCESS)
+ *rid_ret = ainfo.a_rid;
(void) samr_close_handle(&domain_handle);
}
(void) samr_close_handle(&samr_handle);
- mlsvc_free_user_info(user_info);
return (status);
}
-
/*
* sam_get_local_domains
*
@@ -441,8 +397,7 @@
}
static struct samr_sid *
-sam_get_domain_sid(mlsvc_handle_t *samr_handle, char *server, char *domain_name,
- smb_userinfo_t *user_info)
+sam_get_domain_sid(mlsvc_handle_t *samr_handle, char *server, char *domain_name)
{
struct samr_sid *sid;
@@ -461,11 +416,8 @@
sid = (struct samr_sid *)smb_sid_dup(ntdp->sid);
}
} else {
- if (samr_lookup_domain(samr_handle, domain_name, user_info)
- != 0)
- return (NULL);
-
- sid = (struct samr_sid *)smb_sid_dup(user_info->domain_sid);
+ sid = (struct samr_sid *)samr_lookup_domain(samr_handle,
+ domain_name);
}
return (sid);
--- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.h Sun Feb 01 19:44:54 2009 -0700
@@ -19,12 +19,12 @@
* 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_SAMLIB_H
-#define _SMBSRV_SAMLIB_H
+#ifndef _SAMLIB_H
+#define _SAMLIB_H
/*
* Prototypes for the SAM library and RPC client side library interface.
@@ -61,49 +61,26 @@
/*
* samlib.c
*/
-int sam_lookup_user_info(char *server, char *domain_name, char *username,
- smb_userinfo_t *user_info);
-
-DWORD sam_create_trust_account(char *server, char *domain,
- smb_auth_info_t *auth);
-
-DWORD sam_create_account(char *server, char *domain_name, char *account_name,
- smb_auth_info_t *auth, DWORD account_flags);
-
-DWORD sam_remove_trust_account(char *server, char *domain);
-
-DWORD sam_delete_account(char *server, char *domain_name, char *account_name);
-
-DWORD sam_lookup_name(char *server, char *domain_name, char *account_name,
- DWORD *rid_ret);
-
-DWORD sam_get_local_domains(char *server, char *domain_name);
-DWORD sam_check_user(char *server, char *domain_name, char *account_name);
+DWORD sam_create_trust_account(char *, char *, smb_auth_info_t *);
+DWORD sam_create_account(char *, char *, char *, smb_auth_info_t *, DWORD);
+DWORD sam_remove_trust_account(char *, char *);
+DWORD sam_delete_account(char *, char *, char *);
+DWORD sam_get_local_domains(char *, char *);
+DWORD sam_check_user(char *, char *, char *);
/*
* samr_open.c
*/
-int samr_open(char *server, char *domain, char *username,
- DWORD access_mask, mlsvc_handle_t *samr_handle);
-
-int samr_connect(char *server, char *domain, char *username,
- DWORD access_mask, mlsvc_handle_t *samr_handle);
-
-int samr_close_handle(mlsvc_handle_t *handle);
-
-DWORD samr_open_domain(mlsvc_handle_t *samr_handle, DWORD access_mask,
- struct samr_sid *sid, mlsvc_handle_t *domain_handle);
-
-DWORD samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask,
- DWORD rid, mlsvc_handle_t *user_handle);
-
-DWORD samr_delete_user(mlsvc_handle_t *user_handle);
-
-int samr_open_group(mlsvc_handle_t *domain_handle, DWORD rid,
- mlsvc_handle_t *group_handle);
-
-DWORD samr_create_user(mlsvc_handle_t *domain_handle, char *username,
- DWORD account_flags, DWORD *rid, mlsvc_handle_t *user_handle);
+int samr_open(char *, char *, char *, DWORD, mlsvc_handle_t *);
+int samr_connect(char *, char *, char *, DWORD, mlsvc_handle_t *);
+int samr_close_handle(mlsvc_handle_t *);
+DWORD samr_open_domain(mlsvc_handle_t *, DWORD, struct samr_sid *,
+ mlsvc_handle_t *);
+DWORD samr_open_user(mlsvc_handle_t *, DWORD, DWORD, mlsvc_handle_t *);
+DWORD samr_delete_user(mlsvc_handle_t *);
+int samr_open_group(mlsvc_handle_t *, DWORD, mlsvc_handle_t *);
+DWORD samr_create_user(mlsvc_handle_t *, char *, DWORD, DWORD *,
+ mlsvc_handle_t *);
/*
* samr_lookup.c
@@ -140,21 +117,11 @@
};
-int samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name,
- smb_userinfo_t *user_info);
-
-DWORD samr_enum_local_domains(mlsvc_handle_t *samr_handle);
-
-DWORD samr_lookup_domain_names(mlsvc_handle_t *domain_handle, char *name,
- smb_userinfo_t *user_info);
-
-int samr_query_user_info(mlsvc_handle_t *user_handle, WORD switch_value,
- union samr_user_info *user_info);
-
-int samr_query_user_groups(mlsvc_handle_t *user_handle,
- smb_userinfo_t *user_info);
-
-DWORD samr_get_user_pwinfo(mlsvc_handle_t *user_handle);
+smb_sid_t *samr_lookup_domain(mlsvc_handle_t *, char *);
+DWORD samr_enum_local_domains(mlsvc_handle_t *);
+uint32_t samr_lookup_domain_names(mlsvc_handle_t *, char *, smb_account_t *);
+int samr_query_user_info(mlsvc_handle_t *, WORD, union samr_user_info *);
+DWORD samr_get_user_pwinfo(mlsvc_handle_t *);
typedef struct oem_password {
BYTE data[512];
@@ -162,12 +129,11 @@
} oem_password_t;
-int sam_oem_password(oem_password_t *oem_password, unsigned char *new_password,
- unsigned char *old_password);
+int sam_oem_password(oem_password_t *, unsigned char *, unsigned char *);
#ifdef __cplusplus
}
#endif
-#endif /* _SMBSRV_SAMLIB_H */
+#endif /* _SAMLIB_H */
--- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c Sun Feb 01 19:44:54 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.
*/
@@ -51,25 +51,19 @@
* samr_lookup_domain
*
* Lookup up the domain SID for the specified domain name. The handle
- * should be one returned from samr_connect. The results will be
- * returned in user_info - which should have been allocated by the
- * caller. On success sid_name_use will be set to SidTypeDomain.
- *
- * Returns 0 on success, otherwise returns -ve error code.
+ * should be one returned from samr_connect. The allocated memory for
+ * the returned SID must be freed by caller.
*/
-int
-samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name,
- smb_userinfo_t *user_info)
+smb_sid_t *
+samr_lookup_domain(mlsvc_handle_t *samr_handle, char *domain_name)
{
struct samr_LookupDomain arg;
+ smb_sid_t *domsid = NULL;
int opnum;
- int rc;
size_t length;
- if (ndr_is_null_handle(samr_handle) ||
- domain_name == NULL || user_info == NULL) {
- return (-1);
- }
+ if (ndr_is_null_handle(samr_handle) || domain_name == NULL)
+ return (NULL);
opnum = SAMR_OPNUM_LookupDomain;
bzero(&arg, sizeof (struct samr_LookupDomain));
@@ -85,15 +79,11 @@
arg.domain_name.allosize = length;
arg.domain_name.str = (unsigned char *)domain_name;
- rc = ndr_rpc_call(samr_handle, opnum, &arg);
- if (rc == 0) {
- user_info->sid_name_use = SidTypeDomain;
- user_info->domain_sid = smb_sid_dup((smb_sid_t *)arg.sid);
- user_info->domain_name = MEM_STRDUP("ndr", domain_name);
- }
+ if (ndr_rpc_call(samr_handle, opnum, &arg) == 0)
+ domsid = smb_sid_dup((smb_sid_t *)arg.sid);
ndr_rpc_release(samr_handle);
- return (rc);
+ return (domsid);
}
/*
@@ -140,26 +130,27 @@
/*
* samr_lookup_domain_names
*
- * Lookup up a name
- * returned in user_info - which should have been allocated by the
- * caller. On success sid_name_use will be set to SidTypeDomain.
+ * Lookup up the given name in the domain specified by domain_handle.
+ * Upon a successful lookup the information is returned in the account
+ * arg and caller must free allocated memories by calling smb_account_free().
*
- * Returns 0 on success. Otherwise returns an NT status code.
+ * Returns NT status codes.
*/
-DWORD
+uint32_t
samr_lookup_domain_names(mlsvc_handle_t *domain_handle, char *name,
- smb_userinfo_t *user_info)
+ smb_account_t *account)
{
struct samr_LookupNames arg;
int opnum;
- DWORD status;
+ uint32_t status;
size_t length;
if (ndr_is_null_handle(domain_handle) ||
- name == NULL || user_info == NULL) {
+ name == NULL || account == NULL) {
return (NT_STATUS_INVALID_PARAMETER);
}
+ bzero(account, sizeof (smb_account_t));
opnum = SAMR_OPNUM_LookupNames;
bzero(&arg, sizeof (struct samr_LookupNames));
@@ -180,7 +171,7 @@
if (ndr_rpc_call(domain_handle, opnum, &arg) != 0) {
status = NT_STATUS_INVALID_PARAMETER;
- } else if (arg.status != 0) {
+ } else if (arg.status != NT_STATUS_SUCCESS) {
status = NT_SC_VALUE(arg.status);
/*
@@ -189,10 +180,9 @@
if (status != NT_STATUS_NONE_MAPPED)
ndr_rpc_status(domain_handle, opnum, arg.status);
} else {
- user_info->name = MEM_STRDUP("ndr", name);
- user_info->sid_name_use = arg.rid_types.rid_type[0];
- user_info->rid = arg.rids.rid[0];
- status = 0;
+ account->a_type = arg.rid_types.rid_type[0];
+ account->a_rid = arg.rids.rid[0];
+ status = NT_STATUS_SUCCESS;
}
ndr_rpc_release(domain_handle);
@@ -248,7 +238,8 @@
*
* Returns 0 on success, otherwise returns -1.
*/
-static int samr_setup_user_info(WORD switch_value,
+static int
+samr_setup_user_info(WORD switch_value,
struct samr_QueryUserInfo *arg, union samr_user_info *user_info)
{
struct samr_QueryUserInfo1 *info1;
@@ -312,14 +303,15 @@
* Returns 0 on success, otherwise returns -1.
*/
int
-samr_query_user_groups(mlsvc_handle_t *user_handle, smb_userinfo_t *user_info)
+samr_query_user_groups(mlsvc_handle_t *user_handle, int *n_groups,
+ struct samr_UserGroups **groups)
{
struct samr_QueryUserGroups arg;
int opnum;
int rc;
int nbytes;
- if (ndr_is_null_handle(user_handle) || user_info == NULL)
+ if (ndr_is_null_handle(user_handle))
return (-1);
opnum = SAMR_OPNUM_QueryUserGroups;
@@ -335,15 +327,13 @@
} else {
nbytes = arg.info->n_entry *
sizeof (struct samr_UserGroups);
- user_info->groups = malloc(nbytes);
- if (user_info->groups == NULL) {
- user_info->n_groups = 0;
+ if ((*groups = malloc(nbytes)) == NULL) {
+ *n_groups = 0;
rc = -1;
} else {
- user_info->n_groups = arg.info->n_entry;
- (void) memcpy(user_info->groups,
- arg.info->groups, nbytes);
+ *n_groups = arg.info->n_entry;
+ bcopy(arg.info->groups, *groups, nbytes);
}
}
}
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_logon.c Sun Feb 01 19:44:54 2009 -0700
@@ -41,18 +41,17 @@
#include <smbsrv/smb_token.h>
#include <lsalib.h>
-extern uint32_t netlogon_logon(netr_client_t *clnt, smb_userinfo_t *uinfo);
-static uint32_t smb_logon_domain(netr_client_t *clnt, smb_userinfo_t *uinfo);
-static uint32_t smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo);
-static uint32_t smb_logon_none(netr_client_t *clnt, smb_userinfo_t *uinfo);
+extern uint32_t netlogon_logon(netr_client_t *, smb_token_t *);
+static uint32_t smb_logon_domain(netr_client_t *, smb_token_t *);
+static uint32_t smb_logon_local(netr_client_t *, smb_token_t *);
+static uint32_t smb_logon_anon(netr_client_t *, smb_token_t *);
-static uint32_t smb_setup_luinfo(smb_userinfo_t *, netr_client_t *, uid_t);
+static uint32_t smb_token_setup_local(smb_passwd_t *, smb_token_t *);
+static uint32_t smb_token_setup_anon(smb_token_t *token);
-static int smb_token_is_member(smb_token_t *token, smb_sid_t *sid);
-static int smb_token_is_valid(smb_token_t *token);
-static smb_win_grps_t *smb_token_create_wingrps(smb_userinfo_t *user_info);
-
-static smb_posix_grps_t *smb_token_create_pxgrps(uid_t uid);
+static boolean_t smb_token_is_member(smb_token_t *, smb_sid_t *);
+static uint32_t smb_token_setup_wingrps(smb_token_t *);
+static smb_posix_grps_t *smb_token_create_pxgrps(uid_t);
/* Consolidation private function from Network Repository */
extern int _getgroupsbymember(const char *, gid_t[], int, int);
@@ -71,43 +70,43 @@
sim = sib->sib_maps;
if (token->tkn_flags & SMB_ATF_ANON) {
- token->tkn_user->i_id = UID_NOBODY;
- token->tkn_owner->i_id = UID_NOBODY;
+ token->tkn_user.i_id = UID_NOBODY;
+ token->tkn_owner.i_id = UID_NOBODY;
} else {
/* User SID */
- id = token->tkn_user;
+ id = &token->tkn_user;
sim->sim_id = &id->i_id;
stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
- id->i_sidattr.sid, SMB_IDMAP_USER);
+ id->i_sid, SMB_IDMAP_USER);
if (stat != IDMAP_SUCCESS)
return (stat);
/* Owner SID */
- id = token->tkn_owner;
+ id = &token->tkn_owner;
sim->sim_id = &id->i_id;
stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
- id->i_sidattr.sid, SMB_IDMAP_USER);
+ id->i_sid, SMB_IDMAP_USER);
if (stat != IDMAP_SUCCESS)
return (stat);
}
/* Primary Group SID */
- id = token->tkn_primary_grp;
+ id = &token->tkn_primary_grp;
sim->sim_id = &id->i_id;
- stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++,
- id->i_sidattr.sid, SMB_IDMAP_GROUP);
+ stat = smb_idmap_batch_getid(sib->sib_idmaph, sim++, id->i_sid,
+ SMB_IDMAP_GROUP);
if (stat != IDMAP_SUCCESS)
return (stat);
/* Other Windows Group SIDs */
- for (i = 0; i < token->tkn_win_grps->wg_count; i++, sim++) {
- id = &token->tkn_win_grps->wg_groups[i];
+ for (i = 0; i < token->tkn_win_grps.i_cnt; i++, sim++) {
+ id = &token->tkn_win_grps.i_ids[i];
sim->sim_id = &id->i_id;
stat = smb_idmap_batch_getid(sib->sib_idmaph, sim,
- id->i_sidattr.sid, SMB_IDMAP_GROUP);
+ id->i_sid, SMB_IDMAP_GROUP);
if (stat != IDMAP_SUCCESS)
break;
@@ -132,17 +131,12 @@
/*
* Number of idmap lookups: user SID, owner SID, primary group SID,
- * and all Windows group SIDs
+ * and all Windows group SIDs. Skip user/owner SID for Anonymous.
*/
if (token->tkn_flags & SMB_ATF_ANON)
- /*
- * Don't include user and owner SID, they're Anonymous
- */
- nmaps = 1;
+ nmaps = token->tkn_win_grps.i_cnt + 1;
else
- nmaps = 3;
-
- nmaps += token->tkn_win_grps->wg_count;
+ nmaps = token->tkn_win_grps.i_cnt + 3;
do {
stat = smb_idmap_batch_create(&sib, nmaps, SMB_IDMAP_SID2ID);
@@ -245,61 +239,18 @@
void
smb_token_destroy(smb_token_t *token)
{
- smb_win_grps_t *groups;
- int i;
-
- if (token == NULL)
- return;
-
- if (token->tkn_user) {
- free(token->tkn_user->i_sidattr.sid);
- free(token->tkn_user);
- }
-
- if (token->tkn_owner) {
- free(token->tkn_owner->i_sidattr.sid);
- free(token->tkn_owner);
- }
-
- if (token->tkn_primary_grp) {
- free(token->tkn_primary_grp->i_sidattr.sid);
- free(token->tkn_primary_grp);
- }
-
- if ((groups = token->tkn_win_grps) != NULL) {
- for (i = 0; i < groups->wg_count; ++i)
- free(groups->wg_groups[i].i_sidattr.sid);
- free(groups);
+ if (token != NULL) {
+ smb_sid_free(token->tkn_user.i_sid);
+ smb_sid_free(token->tkn_owner.i_sid);
+ smb_sid_free(token->tkn_primary_grp.i_sid);
+ smb_ids_free(&token->tkn_win_grps);
+ smb_privset_free(token->tkn_privileges);
+ free(token->tkn_posix_grps);
+ free(token->tkn_account_name);
+ free(token->tkn_domain_name);
+ free(token->tkn_session_key);
+ free(token);
}
-
- smb_privset_free(token->tkn_privileges);
-
- free(token->tkn_posix_grps);
- free(token->tkn_account_name);
- free(token->tkn_domain_name);
- free(token->tkn_session_key);
-
- free(token);
-}
-
-static smb_id_t *
-smb_token_create_id(smb_sid_t *sid)
-{
- smb_id_t *id;
-
- if ((id = malloc(sizeof (smb_id_t))) == NULL)
- return (NULL);
-
- id->i_id = (uid_t)-1;
- id->i_sidattr.attrs = 7;
- id->i_sidattr.sid = smb_sid_dup(sid);
-
- if (id->i_sidattr.sid == NULL) {
- free(id);
- id = NULL;
- }
-
- return (id);
}
/*
@@ -308,28 +259,26 @@
* 1. The logged on user is a member of Domain Admins group
* 2. he/she is a member of local Administrators group
*/
-static smb_id_t *
-smb_token_create_owner(smb_userinfo_t *user_info)
+static void
+smb_token_set_owner(smb_token_t *token)
{
#ifdef SMB_SUPPORT_GROUP_OWNER
smb_sid_t *owner_sid;
- smb_wka_t *wka;
- if (user_info->flags & SMB_UINFO_FLAG_ADMIN) {
- wka = smb_wka_lookup("Administrators");
- assert(wka);
- owner_sid = wka->wka_binsid;
+ if (token->tkn_flags & SMB_ATF_ADMIN) {
+ owner_sid = smb_wka_get_sid("Administrators");
+ assert(owner_sid);
} else {
- owner_sid = user_info->user_sid;
+ owner_sid = token->tkn_user->i_sid;
}
- return (smb_token_create_id(owner_sid));
+ token->tkn_owner.i_sid = smb_sid_dup(owner_sid);
#endif
- return (smb_token_create_id(user_info->user_sid));
+ token->tkn_owner.i_sid = smb_sid_dup(token->tkn_user.i_sid);
}
static smb_privset_t *
-smb_token_create_privs(smb_userinfo_t *user_info)
+smb_token_create_privs(smb_token_t *token)
{
smb_privset_t *privs;
smb_giter_t gi;
@@ -346,14 +295,13 @@
}
while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
- if (smb_lgrp_is_member(&grp, user_info->user_sid)) {
+ if (smb_lgrp_is_member(&grp, token->tkn_user.i_sid))
smb_privset_merge(privs, grp.sg_privs);
- }
smb_lgrp_free(&grp);
}
smb_lgrp_iterclose(&gi);
- if (user_info->flags & SMB_UINFO_FLAG_ADMIN) {
+ if (token->tkn_flags & SMB_ATF_ADMIN) {
rc = smb_lgrp_getbyname("Administrators", &grp);
if (rc == SMB_LGRP_SUCCESS) {
smb_privset_merge(privs, grp.sg_privs);
@@ -370,248 +318,57 @@
}
static void
-smb_token_set_flags(smb_token_t *token, smb_userinfo_t *user_info)
+smb_token_set_flags(smb_token_t *token)
{
- smb_wka_t *wka;
+ uint32_t rid;
- if (user_info->flags & SMB_UINFO_FLAG_ANON) {
- token->tkn_flags |= SMB_ATF_ANON;
- return;
- }
-
- if (user_info->rid == DOMAIN_USER_RID_GUEST) {
+ (void) smb_sid_getrid(token->tkn_user.i_sid, &rid);
+ if (rid == DOMAIN_USER_RID_GUEST) {
token->tkn_flags |= SMB_ATF_GUEST;
return;
}
- wka = smb_wka_lookup("Administrators");
- if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
+ if (smb_token_is_member(token, smb_wka_get_sid("Administrators")))
token->tkn_flags |= SMB_ATF_ADMIN;
- wka = smb_wka_lookup("Power Users");
- if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
+ if (smb_token_is_member(token, smb_wka_get_sid("Power Users")))
token->tkn_flags |= SMB_ATF_POWERUSER;
- wka = smb_wka_lookup("Backup Operators");
- if (wka->wka_binsid && smb_token_is_member(token, wka->wka_binsid))
+ if (smb_token_is_member(token, smb_wka_get_sid("Backup Operators")))
token->tkn_flags |= SMB_ATF_BACKUPOP;
-
-}
-
-/*
- * smb_token_create
- *
- * Build an access token based on the given user information (user_info).
- *
- * If everything is successful, a pointer to an access token is
- * returned. Otherwise a null pointer is returned.
- */
-static smb_token_t *
-smb_token_create(smb_userinfo_t *user_info)
-{
- smb_token_t *token;
-
- if (user_info->sid_name_use != SidTypeUser)
- return (NULL);
-
- token = (smb_token_t *)malloc(sizeof (smb_token_t));
- if (token == NULL) {
- syslog(LOG_ERR, "smb_token_create: resource shortage");
- return (NULL);
- }
- bzero(token, sizeof (smb_token_t));
-
- /* User */
- token->tkn_user = smb_token_create_id(user_info->user_sid);
- if (token->tkn_user == NULL) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- /* Owner */
- token->tkn_owner = smb_token_create_owner(user_info);
- if (token->tkn_owner == NULL) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- /* Primary Group */
- token->tkn_primary_grp = smb_token_create_id(user_info->pgrp_sid);
- if (token->tkn_primary_grp == NULL) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- /* Privileges */
- token->tkn_privileges = smb_token_create_privs(user_info);
- if (token->tkn_privileges == NULL) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- /* Windows Groups */
- token->tkn_win_grps = smb_token_create_wingrps(user_info);
-
- smb_token_set_flags(token, user_info);
-
- /*
- * IMPORTANT
- *
- * This function has to be called after all the SIDs in the
- * token are setup (i.e. user, owner, primary and supplementary
- * groups) and before setting up Solaris groups.
- */
- if (smb_token_sids2ids(token) != 0) {
- syslog(LOG_ERR, "%s\\%s: idmap failed",
- (user_info->domain_name) ? user_info->domain_name : "",
- (user_info->name) ? user_info->name : "");
- smb_token_destroy(token);
- return (NULL);
- }
-
- /* Solaris Groups */
- token->tkn_posix_grps = smb_token_create_pxgrps(token->tkn_user->i_id);
-
- if (user_info->session_key) {
- token->tkn_session_key = malloc(sizeof (smb_session_key_t));
- if (token->tkn_session_key == NULL) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- (void) memcpy(token->tkn_session_key,
- user_info->session_key, sizeof (smb_session_key_t));
- }
-
- token->tkn_account_name = strdup(user_info->name);
- token->tkn_domain_name = strdup(user_info->domain_name);
-
- if (!smb_token_is_valid(token)) {
- smb_token_destroy(token);
- return (NULL);
- }
-
- return (token);
}
/*
- * smb_token_create_wingrps
+ * Common token setup for both local and domain users.
+ * This function must be called after the initial setup
+ * has been done.
*
- * This private function supports smb_token_create() by mapping the group
- * information in the user_info structure to the form required in an
- * access token. The main difference is that the user_info contains
- * RIDs while and access token contains full SIDs. Memory allocated
- * here will be deallocated as part of smb_token_destroy().
- *
- * If everything is successful, a pointer to a smb_win_grps_t
- * structure is returned. Otherwise a null pointer is returned.
+ * Note that the order of calls in this function are important.
*/
-static smb_win_grps_t *
-smb_token_create_wingrps(smb_userinfo_t *user_info)
+static uint32_t
+smb_token_setup_common(smb_token_t *token)
{
- static char *wk_grps[] =
- {"Authenticated Users", "NETWORK", "Administrators"};
- smb_win_grps_t *tkn_grps;
- smb_sid_attrs_t *dlg_grps;
- smb_rid_attrs_t *g_grps;
- smb_sid_attrs_t *grp;
- smb_sid_t *builtin_sid;
- smb_giter_t gi;
- smb_group_t lgrp;
- uint32_t n_gg, n_lg, n_dlg, n_wg;
- uint32_t i, j;
- int size, count;
-
- if (user_info == NULL)
- return (NULL);
+ smb_token_set_flags(token);
- n_gg = user_info->n_groups; /* Global Groups */
- n_dlg = user_info->n_other_grps; /* Domain Local Groups */
-
- /* Local Groups */
- (void) smb_lgrp_numbymember(user_info->user_sid, (int *)&n_lg);
-
- /* Well known Groups */
- if ((user_info->flags & SMB_UINFO_FLAG_ADMIN) == SMB_UINFO_FLAG_DADMIN)
- /* if user is a domain admin but not a local admin */
- n_wg = 3;
- else if (user_info->flags & SMB_UINFO_FLAG_ANON)
- n_wg = 0;
- else
- n_wg = 2;
+ smb_token_set_owner(token);
+ if (token->tkn_owner.i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
- count = n_gg + n_dlg + n_lg + n_wg;
- size = sizeof (smb_win_grps_t) + (count * sizeof (smb_id_t));
-
- if ((tkn_grps = malloc(size)) == NULL)
- return (NULL);
- bzero(tkn_grps, size);
+ /* Privileges */
+ token->tkn_privileges = smb_token_create_privs(token);
+ if (token->tkn_privileges == NULL)
+ return (NT_STATUS_NO_MEMORY);
- /* Add global groups */
- g_grps = user_info->groups;
- for (i = 0; i < n_gg; i++) {
- grp = &tkn_grps->wg_groups[i].i_sidattr;
- grp->sid = smb_sid_splice(user_info->domain_sid, g_grps[i].rid);
- if (grp->sid == NULL)
- break;
- grp->attrs = g_grps[i].attributes;
+ if (smb_token_sids2ids(token) != 0) {
+ syslog(LOG_ERR, "%s\\%s: idmap failed",
+ token->tkn_domain_name, token->tkn_account_name);
+ return (NT_STATUS_INTERNAL_ERROR);
}
- if (n_gg == 0) {
- /*
- * if there's no global group should add the
- * primary group.
- */
- grp = &tkn_grps->wg_groups[i].i_sidattr;
- grp->sid = smb_sid_dup(user_info->pgrp_sid);
- if (grp->sid != NULL) {
- grp->attrs = 0x7;
- i++;
- }
- }
-
- /* Add domain local groups */
- dlg_grps = user_info->other_grps;
- for (j = 0; j < n_dlg; j++, i++) {
- grp = &tkn_grps->wg_groups[i].i_sidattr;
- grp->sid = smb_sid_dup(dlg_grps[j].sid);
- if (grp->sid == NULL)
- break;
- grp->attrs = dlg_grps[j].attrs;
- }
+ /* Solaris Groups */
+ token->tkn_posix_grps = smb_token_create_pxgrps(token->tkn_user.i_id);
- /* Add local groups */
- if (n_lg && (smb_lgrp_iteropen(&gi) == SMB_LGRP_SUCCESS)) {
- j = 0;
- while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
- if ((j < n_lg) &&
- smb_lgrp_is_member(&lgrp, user_info->user_sid)) {
- grp = &tkn_grps->wg_groups[i].i_sidattr;
- grp->sid = smb_sid_dup(lgrp.sg_id.gs_sid);
- if (grp->sid == NULL) {
- smb_lgrp_free(&lgrp);
- break;
- }
- grp->attrs = lgrp.sg_attr;
- i++;
- j++;
- }
- smb_lgrp_free(&lgrp);
- }
- smb_lgrp_iterclose(&gi);
- }
-
- /* Add well known groups */
- for (j = 0; j < n_wg; j++, i++) {
- builtin_sid = smb_wka_lookup_name(wk_grps[j], NULL);
- if (builtin_sid == NULL)
- break;
- tkn_grps->wg_groups[i].i_sidattr.sid = builtin_sid;
- tkn_grps->wg_groups[i].i_sidattr.attrs = 0x7;
- }
-
- tkn_grps->wg_count = i;
- return (tkn_grps);
+ return (NT_STATUS_SUCCESS);
}
/*
@@ -626,38 +383,31 @@
smb_logon(netr_client_t *clnt)
{
smb_token_t *token = NULL;
- smb_userinfo_t *uinfo;
uint32_t status;
- if ((uinfo = mlsvc_alloc_user_info()) == 0)
+ if ((token = malloc(sizeof (smb_token_t))) == NULL) {
+ syslog(LOG_ERR, "smb_logon: resource shortage");
return (NULL);
-
- switch (clnt->flags) {
- case NETR_CFLG_DOMAIN:
- /* Pass through authentication with DC */
- status = smb_logon_domain(clnt, uinfo);
- break;
+ }
+ bzero(token, sizeof (smb_token_t));
- case NETR_CFLG_LOCAL:
- /* Local authentication */
- status = smb_logon_local(clnt, uinfo);
- break;
-
- case NETR_CFLG_ANON:
- /* Anonymous user; no authentication */
- status = smb_logon_none(clnt, uinfo);
- break;
-
- default:
- status = NT_STATUS_INVALID_PARAMETER;
- break;
+ status = smb_logon_anon(clnt, token);
+ if (status == NT_STATUS_INVALID_LOGON_TYPE) {
+ status = smb_logon_local(clnt, token);
+ if (status != NT_STATUS_SUCCESS) {
+ if ((status == NT_STATUS_INVALID_LOGON_TYPE) ||
+ (*clnt->real_domain == '\0'))
+ status = smb_logon_domain(clnt, token);
+ }
}
- if (status == NT_STATUS_SUCCESS)
- token = smb_token_create(uinfo);
+ if (status == NT_STATUS_SUCCESS) {
+ if (smb_token_setup_common(token) == NT_STATUS_SUCCESS)
+ return (token);
+ }
- mlsvc_free_user_info(uinfo);
- return (token);
+ smb_token_destroy(token);
+ return (NULL);
}
/*
@@ -666,15 +416,15 @@
* Performs pass through authentication with PDC.
*/
static uint32_t
-smb_logon_domain(netr_client_t *clnt, smb_userinfo_t *uinfo)
+smb_logon_domain(netr_client_t *clnt, smb_token_t *token)
{
uint32_t status;
- if ((status = netlogon_logon(clnt, uinfo)) != 0) {
+ if ((status = netlogon_logon(clnt, token)) != 0) {
if (status == NT_STATUS_CANT_ACCESS_DOMAIN_INFO) {
- if ((status = netlogon_logon(clnt, uinfo)) != 0) {
+ if ((status = netlogon_logon(clnt, token)) != 0) {
syslog(LOG_INFO, "SmbLogon[%s\\%s]: %s",
- clnt->domain, clnt->username,
+ clnt->real_domain, clnt->real_username,
xlate_nt_status(status));
return (status);
}
@@ -692,20 +442,28 @@
* hash with user's password(s) to authenticate the user.
*/
static uint32_t
-smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo)
+smb_logon_local(netr_client_t *clnt, smb_token_t *token)
{
smb_passwd_t smbpw;
boolean_t lm_ok, nt_ok;
uint32_t status;
+ nt_domain_t *domain;
- if (smb_pwd_getpwnam(clnt->username, &smbpw) == NULL) {
+ /* Make sure this is not a domain user */
+ if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) {
+ domain = nt_domain_lookup_name(clnt->real_domain);
+ if (domain && (domain->type != NT_DOMAIN_LOCAL))
+ return (NT_STATUS_INVALID_LOGON_TYPE);
+ }
+
+ if (smb_pwd_getpwnam(clnt->real_username, &smbpw) == NULL) {
/*
* If user doesn't have entry either in smbpasswd
* or passwd it's considered as an invalid user.
*/
status = NT_STATUS_NO_SUCH_USER;
syslog(LOG_NOTICE, "SmbLogon[%s\\%s]: %s",
- clnt->domain, clnt->username,
+ clnt->real_domain, clnt->real_username,
xlate_nt_status(status));
return (status);
}
@@ -723,12 +481,12 @@
clnt->lm_password.lm_password_len,
clnt->domain,
clnt->username);
- uinfo->session_key = NULL;
+ token->tkn_session_key = NULL;
}
if (!lm_ok && (clnt->nt_password.nt_password_len != 0)) {
- if ((uinfo->session_key =
- malloc(SMBAUTH_SESSION_KEY_SZ)) == NULL)
+ token->tkn_session_key = malloc(SMBAUTH_SESSION_KEY_SZ);
+ if (token->tkn_session_key == NULL)
return (NT_STATUS_NO_MEMORY);
nt_ok = smb_auth_validate_nt(
clnt->challenge_key.challenge_key_val,
@@ -738,84 +496,67 @@
clnt->nt_password.nt_password_len,
clnt->domain,
clnt->username,
- (uchar_t *)uinfo->session_key);
+ (uchar_t *)token->tkn_session_key);
}
if (!nt_ok && !lm_ok) {
status = NT_STATUS_WRONG_PASSWORD;
syslog(LOG_NOTICE, "SmbLogon[%s\\%s]: %s",
- clnt->domain, clnt->username,
+ clnt->real_domain, clnt->real_username,
xlate_nt_status(status));
return (status);
}
- status = smb_setup_luinfo(uinfo, clnt, smbpw.pw_uid);
+ status = smb_token_setup_local(&smbpw, token);
return (status);
}
/*
- * smb_logon_none
- *
- * Setup user information for anonymous user.
- * No authentication is required.
+ * If 'clnt' represents an anonymous user (no password)
+ * then setup the token accordingly, otherwise return
+ * NT_STATUS_INVALID_LOGON_TYPE
*/
static uint32_t
-smb_logon_none(netr_client_t *clnt, smb_userinfo_t *uinfo)
+smb_logon_anon(netr_client_t *clnt, smb_token_t *token)
{
- return (smb_setup_luinfo(uinfo, clnt, (uid_t)-1));
+ if ((clnt->nt_password.nt_password_len == 0) &&
+ (clnt->lm_password.lm_password_len == 0 ||
+ (clnt->lm_password.lm_password_len == 1 &&
+ *clnt->lm_password.lm_password_val == '\0'))) {
+ return (smb_token_setup_anon(token));
+ }
+
+ return (NT_STATUS_INVALID_LOGON_TYPE);
}
/*
- * smb_setup_luinfo
- *
- * Setup local user information based on the client information and
- * user's record in the local password file.
+ * Setup an access token for the specified local user.
*/
static uint32_t
-smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid)
+smb_token_setup_local(smb_passwd_t *smbpw, smb_token_t *token)
{
idmap_stat stat;
smb_idmap_batch_t sib;
smb_idmap_t *umap, *gmap;
- smb_group_t grp;
struct passwd pw;
char pwbuf[1024];
char nbname[NETBIOS_NAME_SZ];
(void) smb_getnetbiosname(nbname, sizeof (nbname));
- lui->sid_name_use = SidTypeUser;
- lui->domain_sid = smb_sid_dup(nt_domain_local_sid());
- lui->name = strdup(clnt->username);
- lui->domain_name = strdup(nbname);
- lui->n_groups = 0;
- lui->groups = NULL;
- lui->n_other_grps = 0;
- lui->other_grps = NULL;
- lui->flags = 0;
+ token->tkn_account_name = strdup(smbpw->pw_name);
+ token->tkn_domain_name = strdup(nbname);
- if (lui->name == NULL || lui->domain_name == NULL ||
- lui->domain_sid == NULL)
- return (NT_STATUS_INVALID_PARAMETER);
+ if (token->tkn_account_name == NULL ||
+ token->tkn_domain_name == NULL)
+ return (NT_STATUS_NO_MEMORY);
- if (clnt->flags & NETR_CFLG_ANON) {
- lui->user_sid = smb_wka_lookup_name("Anonymous", NULL);
- lui->pgrp_sid = smb_wka_lookup_name("Anonymous", NULL);
- lui->flags = SMB_UINFO_FLAG_ANON;
-
- if (lui->user_sid == NULL || lui->pgrp_sid == NULL)
- return (NT_STATUS_NO_MEMORY);
-
- return (NT_STATUS_SUCCESS);
- }
-
- if (getpwuid_r(uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
+ if (getpwuid_r(smbpw->pw_uid, &pw, pwbuf, sizeof (pwbuf)) == NULL)
return (NT_STATUS_NO_SUCH_USER);
/* Get the SID for user's uid & gid */
stat = smb_idmap_batch_create(&sib, 2, SMB_IDMAP_ID2SID);
- if (stat != IDMAP_SUCCESS) {
+ if (stat != IDMAP_SUCCESS)
return (NT_STATUS_INTERNAL_ERROR);
- }
umap = &sib.sib_maps[0];
stat = smb_idmap_batch_getsid(sib.sib_idmaph, umap, pw.pw_uid,
@@ -835,54 +576,45 @@
return (NT_STATUS_INTERNAL_ERROR);
}
- stat = smb_idmap_batch_getmappings(&sib);
-
- if (stat != IDMAP_SUCCESS) {
+ if (smb_idmap_batch_getmappings(&sib) != IDMAP_SUCCESS)
return (NT_STATUS_INTERNAL_ERROR);
- }
- lui->rid = umap->sim_rid;
- lui->user_sid = smb_sid_dup(umap->sim_sid);
-
- lui->primary_group_rid = gmap->sim_rid;
- lui->pgrp_sid = smb_sid_dup(gmap->sim_sid);
+ token->tkn_user.i_sid = smb_sid_dup(umap->sim_sid);
+ token->tkn_primary_grp.i_sid = smb_sid_dup(gmap->sim_sid);
smb_idmap_batch_destroy(&sib);
- if ((lui->user_sid == NULL) || (lui->pgrp_sid == NULL))
+ if (token->tkn_user.i_sid == NULL ||
+ token->tkn_primary_grp.i_sid == NULL)
return (NT_STATUS_NO_MEMORY);
- if (smb_lgrp_getbyname("Administrators", &grp) == SMB_LGRP_SUCCESS) {
- if (smb_lgrp_is_member(&grp, lui->user_sid))
- lui->flags = SMB_UINFO_FLAG_LADMIN;
- smb_lgrp_free(&grp);
- }
-
- return (NT_STATUS_SUCCESS);
+ return (smb_token_setup_wingrps(token));
}
/*
- * smb_token_is_valid
- *
- * check to see if specified fields of the given access
- * token are valid.
- * Returns 1 if all of them are valid; otherwise 0.
+ * Setup access token for an anonymous connection
*/
-static int
-smb_token_is_valid(smb_token_t *token)
+static uint32_t
+smb_token_setup_anon(smb_token_t *token)
{
- int valid;
+ char nbname[NETBIOS_NAME_SZ];
+ smb_sid_t *user_sid;
- valid = (token->tkn_user != 0) &&
- (token->tkn_user->i_sidattr.sid != 0) &&
- (token->tkn_privileges != 0) &&
- (token->tkn_win_grps != 0) &&
- (token->tkn_owner != 0) &&
- (token->tkn_owner->i_sidattr.sid != 0) &&
- (token->tkn_primary_grp != 0) &&
- (token->tkn_primary_grp->i_sidattr.sid != 0);
+ (void) smb_getnetbiosname(nbname, sizeof (nbname));
+ token->tkn_account_name = strdup("Anonymous");
+ token->tkn_domain_name = strdup("NT Authority");
+ user_sid = smb_wka_get_sid("Anonymous");
+ token->tkn_user.i_sid = smb_sid_dup(user_sid);
+ token->tkn_primary_grp.i_sid = smb_sid_dup(user_sid);
+ token->tkn_flags = SMB_ATF_ANON;
- return (valid);
+ if (token->tkn_account_name == NULL ||
+ token->tkn_domain_name == NULL ||
+ token->tkn_user.i_sid == NULL ||
+ token->tkn_primary_grp.i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ return (smb_token_setup_wingrps(token));
}
/*
@@ -894,10 +626,7 @@
static smb_sid_t *
smb_token_user_sid(smb_token_t *token)
{
- if (token && token->tkn_user)
- return ((token)->tkn_user->i_sidattr.sid);
-
- return (NULL);
+ return ((token) ? token->tkn_user.i_sid : NULL);
}
/*
@@ -917,25 +646,21 @@
static smb_sid_t *
smb_token_group_sid(smb_token_t *token, int *iterator)
{
- smb_win_grps_t *groups;
int index;
- if (token == NULL || iterator == NULL) {
+ if (token == NULL || iterator == NULL)
return (NULL);
- }
- if ((groups = token->tkn_win_grps) == NULL) {
+ if (token->tkn_win_grps.i_ids == NULL)
return (NULL);
- }
index = *iterator;
- if (index < 0 || index >= groups->wg_count) {
+ if (index < 0 || index >= token->tkn_win_grps.i_cnt)
return (NULL);
- }
++(*iterator);
- return (groups->wg_groups[index].i_sidattr.sid);
+ return (token->tkn_win_grps.i_ids[index].i_sid);
}
/*
@@ -945,21 +670,24 @@
* member of a token. The user SID and all group SIDs are tested.
* Returns 1 if the SID is a member of the token. Otherwise returns 0.
*/
-static int
+static boolean_t
smb_token_is_member(smb_token_t *token, smb_sid_t *sid)
{
smb_sid_t *tsid;
int iterator = 0;
+ if (token == NULL || sid == NULL)
+ return (B_FALSE);
+
tsid = smb_token_user_sid(token);
while (tsid) {
if (smb_sid_cmp(tsid, sid))
- return (1);
+ return (B_TRUE);
tsid = smb_token_group_sid(token, &iterator);
}
- return (0);
+ return (B_FALSE);
}
/*
@@ -970,9 +698,9 @@
void
smb_token_log(smb_token_t *token)
{
- smb_win_grps_t *w_grps;
+ smb_ids_t *w_grps;
+ smb_id_t *grp;
smb_posix_grps_t *x_grps;
- smb_sid_attrs_t *grp;
char sidstr[SMB_SID_STRSZ];
int i;
@@ -983,54 +711,97 @@
(token->tkn_domain_name) ? token->tkn_domain_name : "-NULL-",
(token->tkn_account_name) ? token->tkn_account_name : "-NULL-");
- syslog(LOG_DEBUG, " User->Attr: %d",
- token->tkn_user->i_sidattr.attrs);
- smb_sid_tostr((smb_sid_t *)token->tkn_user->i_sidattr.sid, sidstr);
- syslog(LOG_DEBUG, " User->Sid: %s (id=%u)",
- sidstr, token->tkn_user->i_id);
+ syslog(LOG_DEBUG, " User->Attr: %d", token->tkn_user.i_attrs);
+ smb_sid_tostr((smb_sid_t *)token->tkn_user.i_sid, sidstr);
+ syslog(LOG_DEBUG, " User->Sid: %s (id=%u)", sidstr,
+ token->tkn_user.i_id);
- smb_sid_tostr((smb_sid_t *)token->tkn_owner->i_sidattr.sid, sidstr);
+ smb_sid_tostr((smb_sid_t *)token->tkn_owner.i_sid, sidstr);
syslog(LOG_DEBUG, " Ownr->Sid: %s (id=%u)",
- sidstr, token->tkn_owner->i_id);
+ sidstr, token->tkn_owner.i_id);
- smb_sid_tostr((smb_sid_t *)token->tkn_primary_grp->i_sidattr.sid,
- sidstr);
+ smb_sid_tostr((smb_sid_t *)token->tkn_primary_grp.i_sid, sidstr);
syslog(LOG_DEBUG, " PGrp->Sid: %s (id=%u)",
- sidstr, token->tkn_primary_grp->i_id);
-
- w_grps = token->tkn_win_grps;
- if (w_grps) {
- syslog(LOG_DEBUG, " Windows groups: %d",
- w_grps->wg_count);
+ sidstr, token->tkn_primary_grp.i_id);
- for (i = 0; i < w_grps->wg_count; ++i) {
- grp = &w_grps->wg_groups[i].i_sidattr;
+ w_grps = &token->tkn_win_grps;
+ if (w_grps->i_ids) {
+ syslog(LOG_DEBUG, " Windows groups: %d", w_grps->i_cnt);
+ grp = w_grps->i_ids;
+ for (i = 0; i < w_grps->i_cnt; ++i, grp++) {
syslog(LOG_DEBUG,
- " Grp[%d].Attr:%d", i, grp->attrs);
- if (w_grps->wg_groups[i].i_sidattr.sid) {
- smb_sid_tostr((smb_sid_t *)grp->sid, sidstr);
+ " Grp[%d].Attr:%d", i, grp->i_attrs);
+ if (grp->i_sid != NULL) {
+ smb_sid_tostr((smb_sid_t *)grp->i_sid, sidstr);
syslog(LOG_DEBUG,
" Grp[%d].Sid: %s (id=%u)", i, sidstr,
- w_grps->wg_groups[i].i_id);
+ grp->i_id);
}
}
+ } else {
+ syslog(LOG_DEBUG, " No Windows groups");
}
- else
- syslog(LOG_DEBUG, " No Windows groups");
x_grps = token->tkn_posix_grps;
if (x_grps) {
- syslog(LOG_DEBUG, " Solaris groups: %d",
- x_grps->pg_ngrps);
+ syslog(LOG_DEBUG, " Solaris groups: %d", x_grps->pg_ngrps);
for (i = 0; i < x_grps->pg_ngrps; i++)
- syslog(LOG_DEBUG, " %u",
- x_grps->pg_grps[i]);
+ syslog(LOG_DEBUG, " %u", x_grps->pg_grps[i]);
+ } else {
+ syslog(LOG_DEBUG, " No Solaris groups");
}
- else
- syslog(LOG_DEBUG, " No Solaris groups");
if (token->tkn_privileges)
smb_privset_log(token->tkn_privileges);
else
syslog(LOG_DEBUG, " No privileges");
}
+
+/*
+ * Sets up local and well-known group membership for the given
+ * token. Two assumptions have been made here:
+ *
+ * a) token already contains a valid user SID so that group
+ * memberships can be established
+ *
+ * b) token belongs to a local or anonymous user
+ */
+static uint32_t
+smb_token_setup_wingrps(smb_token_t *token)
+{
+ smb_ids_t tkn_grps;
+ uint32_t status;
+
+
+ /*
+ * We always want the user's primary group in the list
+ * of groups.
+ */
+ tkn_grps.i_cnt = 1;
+ if ((tkn_grps.i_ids = malloc(sizeof (smb_id_t))) == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ tkn_grps.i_ids->i_sid = smb_sid_dup(token->tkn_primary_grp.i_sid);
+ tkn_grps.i_ids->i_attrs = token->tkn_primary_grp.i_attrs;
+ if (tkn_grps.i_ids->i_sid == NULL) {
+ smb_ids_free(&tkn_grps);
+ return (NT_STATUS_NO_MEMORY);
+ }
+
+ status = smb_sam_usr_groups(token->tkn_user.i_sid, &tkn_grps);
+ if (status != NT_STATUS_SUCCESS) {
+ smb_ids_free(&tkn_grps);
+ return (status);
+ }
+
+ if ((token->tkn_flags & SMB_ATF_ANON) == 0) {
+ status = smb_wka_token_groups(B_FALSE, &tkn_grps);
+ if (status != NT_STATUS_SUCCESS) {
+ smb_ids_free(&tkn_grps);
+ return (status);
+ }
+ }
+
+ token->tkn_win_grps = tkn_grps;
+ return (status);
+}
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Sun Feb 01 19:44:54 2009 -0700
@@ -624,9 +624,11 @@
* Precedence is none is checked first followed by ro then rw if
* needed. If x is wildcard (< 0) then check to see if the other
* values are a match. If a match, that wins.
+ *
+ * ipv6 is wide open for now, see smb_chk_hostaccess
*/
void
-smb_shr_hostaccess(smb_share_t *si, ipaddr_t ipaddr)
+smb_shr_hostaccess(smb_share_t *si, smb_inaddr_t *ipaddr)
{
int acc = SMB_SHRF_ACC_OPEN;
@@ -634,7 +636,8 @@
* Check to see if there area any share level access
* restrictions.
*/
- if (ipaddr != 0 && (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) {
+ if ((!smb_inet_iszero(ipaddr)) &&
+ (si->shr_flags & SMB_SHRF_ACC_ALL) != 0) {
int none = SMB_SHRF_ACC_OPEN;
int rw = SMB_SHRF_ACC_OPEN;
int ro = SMB_SHRF_ACC_OPEN;
@@ -645,7 +648,6 @@
rw = smb_chk_hostaccess(ipaddr, si->shr_access_rw);
if (si->shr_flags & SMB_SHRF_ACC_RO)
ro = smb_chk_hostaccess(ipaddr, si->shr_access_ro);
-
/* make first pass to get basic value */
if (none != 0)
acc = SMB_SHRF_ACC_NONE;
@@ -864,7 +866,6 @@
if (sharename == NULL || *sharename == '\0')
return (NERR_NetNameNotFound);
-
if (smb_shr_cache_lock(SMB_SHR_CACHE_RDLOCK) == NERR_Success) {
cached_si = smb_shr_cache_findent(sharename);
if (cached_si != NULL) {
@@ -874,7 +875,6 @@
smb_shr_cache_unlock();
}
-
return (status);
}
@@ -1323,7 +1323,6 @@
(void) strlcpy(si->shr_path, path, sizeof (si->shr_path));
(void) strlcpy(si->shr_name, rname, sizeof (si->shr_name));
-
sa_free_attr_string(path);
sa_free_attr_string(rname);
--- a/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/srvsvc_svc.c Sun Feb 01 19:44:54 2009 -0700
@@ -36,8 +36,6 @@
#include <netdb.h>
#include <strings.h>
#include <time.h>
-#include <tzfile.h>
-#include <time.h>
#include <thread.h>
#include <ctype.h>
#include <stdlib.h>
@@ -861,7 +859,7 @@
smb_dr_ulist_t *ulist;
smb_opipe_context_t *user;
char *workstation;
- char ipaddr_buf[INET_ADDRSTRLEN];
+ char ipaddr_buf[INET6_ADDRSTRLEN];
int n_users;
int offset = 0;
int i;
@@ -888,8 +886,8 @@
workstation = user->oc_workstation;
if (workstation == NULL || *workstation == '\0') {
- (void) inet_ntop(AF_INET, (char *)&user->oc_ipaddr,
- ipaddr_buf, sizeof (ipaddr_buf));
+ (void) smb_inet_ntop(&user->oc_ipaddr,
+ ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
workstation = ipaddr_buf;
}
@@ -920,7 +918,7 @@
smb_opipe_context_t *user;
char *workstation;
char account[MAXNAMELEN];
- char ipaddr_buf[INET_ADDRSTRLEN];
+ char ipaddr_buf[INET6_ADDRSTRLEN];
int n_users;
int offset = 0;
int i;
@@ -947,8 +945,8 @@
workstation = user->oc_workstation;
if (workstation == NULL || *workstation == '\0') {
- (void) inet_ntop(AF_INET, (char *)&user->oc_ipaddr,
- ipaddr_buf, sizeof (ipaddr_buf));
+ (void) smb_inet_ntop(&user->oc_ipaddr,
+ ipaddr_buf, SMB_IPSTRLEN(user->oc_ipaddr.a_family));
workstation = ipaddr_buf;
}
--- a/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c Sun Feb 01 19:44:54 2009 -0700
@@ -26,10 +26,24 @@
/*
* Windows Registry RPC (WINREG) server-side interface.
*
- * The WINREG RPC interface returns Win32 error codes.
+ * The registry is a database with a hierarchical structure similar to
+ * a file system, with keys in place of directories and values in place
+ * of files. The top level keys are known as root keys and each key can
+ * contain subkeys and values. As with directories and sub-directories,
+ * the terms key and subkey are used interchangeably. Values, analogous
+ * to files, contain data.
*
- * HKLM Hive Key Local Machine
- * HKU Hive Key Users
+ * A specific subkey can be identifies by its fully qualified name (FQN),
+ * which is analogous to a file system path. In the registry, the key
+ * separator is the '\' character, which is reserved and cannot appear
+ * in key or value names. Registry names are case-insensitive.
+ *
+ * For example: HKEY_LOCAL_MACHINE\System\CurrentControlSet
+ *
+ * The HKEY_LOCAL_MACHINE root key contains a subkey call System, and
+ * System contains a subkey called CurrentControlSet.
+ *
+ * The WINREG RPC interface returns Win32 error codes.
*/
#include <sys/utsname.h>
@@ -42,22 +56,13 @@
#include <smbsrv/libmlsvc.h>
#include <smbsrv/ndl/winreg.ndl>
-#define WINREG_LOGR_SYSTEMKEY \
- "System\\CurrentControlSet\\Services\\Eventlog\\System"
-
-/*
- * Local handle management keys.
- */
-static int winreg_hk;
-static int winreg_hklm;
-static int winreg_hkuser;
-static int winreg_hkkey;
-
/*
* List of supported registry keys (case-insensitive).
*/
static char *winreg_keys[] = {
"System\\CurrentControlSet\\Services\\Eventlog",
+ "System\\CurrentControlSet\\Services\\Eventlog\\Application",
+ "System\\CurrentControlSet\\Services\\Eventlog\\Security",
"System\\CurrentControlSet\\Services\\Eventlog\\System",
"System\\CurrentControlSet\\Control\\ProductOptions",
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
@@ -78,12 +83,19 @@
static winreg_keylist_t winreg_keylist;
static boolean_t winreg_key_has_subkey(const char *);
+static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t);
static char *winreg_lookup_value(const char *);
-static char *winreg_lookup_eventlog_registry(char *, char *);
-static int winreg_s_OpenHK(void *, ndr_xa_t *);
+static int winreg_s_OpenHKCR(void *, ndr_xa_t *);
+static int winreg_s_OpenHKCU(void *, ndr_xa_t *);
static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
-static int winreg_s_OpenHKUsers(void *, ndr_xa_t *);
+static int winreg_s_OpenHKPD(void *, ndr_xa_t *);
+static int winreg_s_OpenHKU(void *, ndr_xa_t *);
+static int winreg_s_OpenHKCC(void *, ndr_xa_t *);
+static int winreg_s_OpenHKDD(void *, ndr_xa_t *);
+static int winreg_s_OpenHKPT(void *, ndr_xa_t *);
+static int winreg_s_OpenHKPN(void *, ndr_xa_t *);
+static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *);
static int winreg_s_Close(void *, ndr_xa_t *);
static int winreg_s_CreateKey(void *, ndr_xa_t *);
static int winreg_s_DeleteKey(void *, ndr_xa_t *);
@@ -103,11 +115,11 @@
static int winreg_s_GetVersion(void *, ndr_xa_t *);
static ndr_stub_table_t winreg_stub_table[] = {
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCR },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCU },
+ { winreg_s_OpenHKCR, WINREG_OPNUM_OpenHKCR },
+ { winreg_s_OpenHKCU, WINREG_OPNUM_OpenHKCU },
{ winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPD },
- { winreg_s_OpenHKUsers, WINREG_OPNUM_OpenHKUsers },
+ { winreg_s_OpenHKPD, WINREG_OPNUM_OpenHKPD },
+ { winreg_s_OpenHKU, WINREG_OPNUM_OpenHKUsers },
{ winreg_s_Close, WINREG_OPNUM_Close },
{ winreg_s_CreateKey, WINREG_OPNUM_CreateKey },
{ winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey },
@@ -125,10 +137,10 @@
{ winreg_s_Shutdown, WINREG_OPNUM_Shutdown },
{ winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown },
{ winreg_s_GetVersion, WINREG_OPNUM_GetVersion },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCC },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKDD },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPT },
- { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPN },
+ { winreg_s_OpenHKCC, WINREG_OPNUM_OpenHKCC },
+ { winreg_s_OpenHKDD, WINREG_OPNUM_OpenHKDD },
+ { winreg_s_OpenHKPT, WINREG_OPNUM_OpenHKPT },
+ { winreg_s_OpenHKPN, WINREG_OPNUM_OpenHKPN },
{0}
};
@@ -188,70 +200,80 @@
(void) ndr_svc_register(&winreg_service);
}
-/*
- * winreg_s_OpenHK
- *
- * Stub.
- */
+static int
+winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKCR"));
+}
+
static int
-winreg_s_OpenHK(void *arg, ndr_xa_t *mxa)
+winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKCU"));
+}
+
+static int
+winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKLM"));
+}
+
+static int
+winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa)
{
- struct winreg_OpenHKCR *param = arg;
- ndr_hdid_t *id;
+ return (winreg_s_OpenHK(arg, mxa, "HKPD"));
+}
+
+static int
+winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKU"));
+}
+
+static int
+winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKCC"));
+}
- if ((id = ndr_hdalloc(mxa, &winreg_hk)) == NULL) {
- bzero(¶m->handle, sizeof (winreg_handle_t));
- param->status = ERROR_ACCESS_DENIED;
- } else {
- bcopy(id, ¶m->handle, sizeof (winreg_handle_t));
- param->status = ERROR_SUCCESS;
- }
+static int
+winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKDD"));
+}
- return (NDR_DRC_OK);
+static int
+winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKPT"));
+}
+
+static int
+winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa)
+{
+ return (winreg_s_OpenHK(arg, mxa, "HKPN"));
}
/*
- * winreg_s_OpenHKLM
+ * winreg_s_OpenHK
*
- * This is a request to open the HKLM and get a handle.
- * The client should treat the handle as an opaque object.
- *
- * Status:
- * ERROR_SUCCESS Valid handle returned.
- * ERROR_ACCESS_DENIED Unable to allocate a handle.
+ * Common code to open root HKEYs.
*/
static int
-winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
+winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey)
{
- struct winreg_OpenHKLM *param = arg;
+ struct winreg_OpenHKCR *param = arg;
ndr_hdid_t *id;
+ char *dupkey;
- if ((id = ndr_hdalloc(mxa, &winreg_hklm)) == NULL) {
+ if ((dupkey = strdup(hkey)) == NULL) {
bzero(¶m->handle, sizeof (winreg_handle_t));
- param->status = ERROR_ACCESS_DENIED;
- } else {
- bcopy(id, ¶m->handle, sizeof (winreg_handle_t));
- param->status = ERROR_SUCCESS;
+ param->status = ERROR_NOT_ENOUGH_MEMORY;
+ return (NDR_DRC_OK);
}
- return (NDR_DRC_OK);
-}
-
-/*
- * winreg_s_OpenHKUsers
- *
- * This is a request to get a HKUsers handle. I'm not sure we are
- * ready to fully support this interface yet, mostly due to the need
- * to support subsequent requests, but we may support enough now. It
- * seems okay with regedt32.
- */
-static int
-winreg_s_OpenHKUsers(void *arg, ndr_xa_t *mxa)
-{
- struct winreg_OpenHKUsers *param = arg;
- ndr_hdid_t *id;
-
- if ((id = ndr_hdalloc(mxa, &winreg_hkuser)) == NULL) {
+ if ((id = ndr_hdalloc(mxa, dupkey)) == NULL) {
+ free(dupkey);
bzero(¶m->handle, sizeof (winreg_handle_t));
param->status = ERROR_ACCESS_DENIED;
} else {
@@ -275,6 +297,12 @@
{
struct winreg_Close *param = arg;
ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
+ ndr_handle_t *hd;
+
+ if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
+ free(hd->nh_data);
+ hd->nh_data = NULL;
+ }
ndr_hdfree(mxa, id);
@@ -294,6 +322,7 @@
ndr_handle_t *hd;
winreg_subkey_t *key;
char *subkey;
+ char *dupkey;
DWORD *action;
subkey = (char *)param->subkey.str;
@@ -339,10 +368,17 @@
/*
* Create a new key.
*/
- id = ndr_hdalloc(mxa, &winreg_hkkey);
+ if ((dupkey = strdup(subkey)) == NULL) {
+ bzero(param, sizeof (struct winreg_CreateKey));
+ param->status = ERROR_NOT_ENOUGH_MEMORY;
+ return (NDR_DRC_OK);
+ }
+
+ id = ndr_hdalloc(mxa, dupkey);
key = malloc(sizeof (winreg_subkey_t));
if ((id == NULL) || (key == NULL)) {
+ free(dupkey);
bzero(param, sizeof (struct winreg_CreateKey));
param->status = ERROR_NOT_ENOUGH_MEMORY;
return (NDR_DRC_OK);
@@ -369,6 +405,7 @@
{
struct winreg_DeleteKey *param = arg;
ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
+ ndr_handle_t *hd;
winreg_subkey_t *key;
char *subkey;
@@ -396,6 +433,13 @@
list_remove(&winreg_keylist.kl_list, key);
--winreg_keylist.kl_count;
+
+ hd = ndr_hdlookup(mxa, &key->sk_handle);
+ if (hd != NULL) {
+ free(hd->nh_data);
+ hd->nh_data = NULL;
+ }
+
ndr_hdfree(mxa, &key->sk_handle);
free(key);
param->status = ERROR_SUCCESS;
@@ -433,34 +477,14 @@
return (B_FALSE);
}
-/*
- * winreg_subkey_get_relative_name
- *
- * Each key contains one or more child keys, each called a subkey.
- * For any specified key, its name MUST be unique for any other subkeys that
- * have the same parent key.
- *
- * To accurately identify a given subkey within the key namespace, its fully
- * qualified name (FQN) is used. The FQN MUST consist of the name of the subkey
- * and the name of all of its parent keys all the way to the root of the tree.
- *
- * The "\" character MUST be used as a hierarchy separator to identify each key
- * in the FQN and therefore MUST not be used in the name of a single key.
- * For example, the subkey "MountedDevices" belongs to the subtree
- * HKEY_LOCAL_MACHINE, as shown in the following example.
- *
- * HKEY_LOCAL_MACHINE -> SYSTEM -> MountedDevices
- *
- * The FQN for MountedDevices is HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices.
- * The relative name of the subkey is "MountedDevices". The relative name
- * MUST be used only for operations that are performed on its immediate parent
- * key (SYSTEM in the previous example).
- */
static char *
-winreg_subkey_get_relative_name(const char *subkey)
+winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index)
{
winreg_subkey_t *key;
- char *value;
+ char *entry;
+ char *p;
+ int subkeylen;
+ int count = 0;
if (subkey == NULL)
return (NULL);
@@ -468,14 +492,37 @@
if (list_is_empty(&winreg_keylist.kl_list))
return (NULL);
- key = list_head(&winreg_keylist.kl_list);
- do {
- if (strcasecmp(subkey, key->sk_name) == 0) {
- value = strrchr(key->sk_name, '\\');
- if (value != NULL)
- return (++value);
+ subkeylen = strlen(subkey);
+
+ for (key = list_head(&winreg_keylist.kl_list);
+ key != NULL; key = list_next(&winreg_keylist.kl_list, key)) {
+ if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) {
+ p = key->sk_name + subkeylen;
+
+ if ((*p != '\\') || (*p == '\0')) {
+ /*
+ * Not the same subkey or an exact match.
+ * We're looking for children of subkey.
+ */
+ continue;
+ }
+
+ ++p;
+
+ if (count < index) {
+ ++count;
+ continue;
+ }
+
+ if ((entry = NDR_STRDUP(mxa, p)) == NULL)
+ return (NULL);
+
+ if ((p = strchr(entry, '\\')) != NULL)
+ *p = '\0';
+
+ return (entry);
}
- } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
+ }
return (NULL);
}
@@ -501,45 +548,35 @@
{
struct winreg_EnumKey *param = arg;
ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
- winreg_string_t *name, *class;
- char *value, *namep = NULL, *classp = NULL;
- int slen = 0;
+ ndr_handle_t *hd;
+ char *subkey;
+ char *name = NULL;
- if (ndr_hdlookup(mxa, id) == NULL) {
- bzero(param, sizeof (struct winreg_EnumKey));
- param->status = ERROR_NO_MORE_ITEMS;
- return (NDR_DRC_OK);
- }
+ if ((hd = ndr_hdlookup(mxa, id)) != NULL)
+ name = hd->nh_data;
- if (param->index > 0) {
+ if (hd == NULL || name == NULL) {
bzero(param, sizeof (struct winreg_EnumKey));
param->status = ERROR_NO_MORE_ITEMS;
return (NDR_DRC_OK);
}
- name = (winreg_string_t *)¶m->name_in;
- class = (winreg_string_t *)¶m->class_in;
- if (name->length != 0)
- namep = (char *)name->str;
-
- if (class->length != 0)
- classp = (char *)class->str;
-
- value = winreg_lookup_eventlog_registry(namep, classp);
- if (value == NULL) {
+ subkey = winreg_enum_subkey(mxa, name, param->index);
+ if (subkey == NULL) {
bzero(param, sizeof (struct winreg_EnumKey));
- param->status = ERROR_CANTREAD;
+ param->status = ERROR_NO_MORE_ITEMS;
return (NDR_DRC_OK);
}
- slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t);
- param->name_out.length = slen;
- param->name_out.allosize = slen;
- if ((param->name_out.str = NDR_STRDUP(mxa, value)) == NULL) {
+ if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)¶m->name_out) == -1) {
bzero(param, sizeof (struct winreg_EnumKey));
param->status = ERROR_NOT_ENOUGH_MEMORY;
return (NDR_DRC_OK);
}
+ /*
+ * This request requires that the length includes the null.
+ */
+ param->name_out.length = param->name_out.allosize;
param->status = ERROR_SUCCESS;
return (NDR_DRC_OK);
@@ -631,8 +668,9 @@
char *subkey = (char *)param->name.str;
ndr_hdid_t *id = NULL;
winreg_subkey_t *key;
+ char *dupkey;
- if (list_is_empty(&winreg_keylist.kl_list)) {
+ if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) {
bzero(¶m->result_handle, sizeof (winreg_handle_t));
param->status = ERROR_FILE_NOT_FOUND;
return (NDR_DRC_OK);
@@ -641,10 +679,16 @@
key = list_head(&winreg_keylist.kl_list);
do {
if (strcasecmp(subkey, key->sk_name) == 0) {
- if (key->sk_predefined == B_TRUE)
- id = ndr_hdalloc(mxa, &winreg_hkkey);
- else
+ if (key->sk_predefined == B_TRUE) {
+ if ((dupkey = strdup(subkey)) == NULL)
+ break;
+
+ id = ndr_hdalloc(mxa, dupkey);
+ if (id == NULL)
+ free(dupkey);
+ } else {
id = &key->sk_handle;
+ }
if (id == NULL)
break;
@@ -790,22 +834,6 @@
}
/*
- * winreg_lookup_eventlog_registry
- *
- * Return the subkey of the specified EventLog key. Decoding of
- * class paramater not yet supported.
- */
-/*ARGSUSED*/
-static char *
-winreg_lookup_eventlog_registry(char *name, char *class)
-{
- if (name == NULL)
- return (winreg_subkey_get_relative_name(WINREG_LOGR_SYSTEMKEY));
-
- return (winreg_subkey_get_relative_name(name));
-}
-
-/*
* winreg_s_SetKeySec
*/
/*ARGSUSED*/
--- a/usr/src/lib/smbsrv/libsmb/Makefile.com Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/Makefile.com Sun Feb 01 19:44:54 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.
#
@@ -28,6 +28,7 @@
OBJS_SHARED = \
smb_common_door_decode.o \
+ smb_inet.o \
smb_match.o \
smb_msgbuf.o \
smb_native.o \
@@ -62,6 +63,7 @@
smb_nicmon.o \
smb_pwdutil.o \
smb_privilege.o \
+ smb_sam.o \
smb_scfutil.o \
smb_util.o \
smb_wksids.o
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h Sun Feb 01 19:44:54 2009 -0700
@@ -34,6 +34,7 @@
#include <sys/list.h>
#include <arpa/inet.h>
#include <net/if.h>
+#include <inet/tcp.h>
#include <netdb.h>
#include <stdlib.h>
#include <libscf.h>
@@ -140,6 +141,7 @@
SMB_CI_KPASSWD_DOMAIN,
SMB_CI_KPASSWD_SEQNUM,
SMB_CI_NETLOGON_SEQNUM,
+ SMB_CI_IPV6_ENABLE,
SMB_CI_MAX
} smb_cfg_id_t;
@@ -183,7 +185,7 @@
extern int smb_config_set_secmode(int);
extern int smb_config_set_idmap_domain(char *);
extern int smb_config_refresh_idmap(void);
-
+extern int smb_config_getip(smb_cfg_id_t, smb_inaddr_t *);
extern void smb_load_kconfig(smb_kmod_cfg_t *kcfg);
extern uint32_t smb_crc_gen(uint8_t *, size_t);
@@ -220,7 +222,7 @@
char *guid);
extern void smb_config_setdomaininfo(char *domain, char *fqdn, char *forest,
char *guid);
-extern uint32_t smb_get_dcinfo(char *, uint32_t, uint32_t *);
+extern uint32_t smb_get_dcinfo(char *, uint32_t, smb_inaddr_t *);
/*
* buffer context structure. This is used to keep track of the buffer
@@ -270,10 +272,10 @@
extern smb_sid_t *smb_getdomainsid(void);
-extern int smb_get_nameservers(struct in_addr *, int);
+extern int smb_get_nameservers(smb_inaddr_t *, int);
extern void smb_tonetbiosname(char *, char *, char);
-extern int smb_chk_hostaccess(ipaddr_t, char *);
+extern int smb_chk_hostaccess(smb_inaddr_t *, char *);
void smb_trace(const char *s);
void smb_tracef(const char *fmt, ...);
@@ -446,7 +448,6 @@
extern smb_passwd_t *smb_pwd_getpwuid(uid_t, smb_passwd_t *);
extern int smb_pwd_setpasswd(const char *, const char *);
extern int smb_pwd_setcntl(const char *, int);
-extern int smb_pwd_num(void);
extern int smb_pwd_iteropen(smb_pwditer_t *);
extern smb_luser_t *smb_pwd_iterate(smb_pwditer_t *);
@@ -637,8 +638,6 @@
int smb_lgrp_del_member(char *, smb_sid_t *, uint16_t);
int smb_lgrp_getbyname(char *, smb_group_t *);
int smb_lgrp_getbyrid(uint32_t, smb_gdomain_t, smb_group_t *);
-int smb_lgrp_numbydomain(smb_gdomain_t, int *);
-int smb_lgrp_numbymember(smb_sid_t *, int *);
void smb_lgrp_free(smb_group_t *);
boolean_t smb_lgrp_is_member(smb_group_t *, smb_sid_t *);
char *smb_lgrp_strerror(int);
@@ -702,7 +701,7 @@
char nic_nbname[NETBIOS_NAME_SZ];
char nic_cmnt[SMB_PI_MAX_COMMENT];
char nic_ifname[LIFNAMSIZ];
- uint32_t nic_ip;
+ smb_inaddr_t nic_ip;
uint32_t nic_mask;
uint32_t nic_bcast;
uint32_t nic_smbflags;
@@ -723,7 +722,7 @@
int smb_nic_delhost(const char *);
int smb_nic_getfirst(smb_niciter_t *);
int smb_nic_getnext(smb_niciter_t *);
-boolean_t smb_nic_exists(uint32_t, boolean_t);
+boolean_t smb_nic_exists(smb_inaddr_t *, boolean_t);
/* NIC Monitoring functions */
int smb_nicmon_start(const char *);
@@ -764,12 +763,31 @@
*/
int smb_wka_init(void);
void smb_wka_fini(void);
-smb_wka_t *smb_wka_lookup(char *);
-char *smb_wka_lookup_sid(smb_sid_t *, uint16_t *);
-smb_sid_t *smb_wka_lookup_name(char *, uint16_t *);
-char *smb_wka_lookup_domain(char *);
-boolean_t smb_wka_is_wellknown(char *);
+smb_wka_t *smb_wka_lookup_name(char *);
+smb_wka_t *smb_wka_lookup_sid(smb_sid_t *);
+smb_sid_t *smb_wka_get_sid(char *);
char *smb_wka_get_domain(int);
+uint32_t smb_wka_token_groups(boolean_t, smb_ids_t *);
+
+/*
+ * In memory account representation
+ */
+typedef struct smb_account {
+ char *a_name;
+ char *a_domain;
+ uint16_t a_type;
+ smb_sid_t *a_sid;
+ smb_sid_t *a_domsid;
+ uint32_t a_rid;
+} smb_account_t;
+
+uint32_t smb_sam_lookup_name(char *, char *, uint16_t, smb_account_t *);
+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);
+void smb_account_free(smb_account_t *);
+boolean_t smb_account_validate(smb_account_t *);
#ifdef __cplusplus
}
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers Sun Feb 01 19:44:54 2009 -0700
@@ -87,6 +87,8 @@
oemstounicodes;
rand_hash;
randomize;
+ smb_account_free;
+ smb_account_validate;
smb_auth_DES;
smb_auth_gen_session_key;
smb_auth_hmac_md5;
@@ -103,6 +105,7 @@
smb_config_get_secmode;
smb_config_getbool;
smb_config_getdomaininfo;
+ smb_config_getip;
smb_config_getname;
smb_config_getnum;
smb_config_getstr;
@@ -183,7 +186,11 @@
smb_idmap_restart;
smb_idmap_start;
smb_idmap_stop;
+ smb_ids_free;
smb_ishostname;
+ smb_inet_equal;
+ smb_inet_iszero;
+ smb_inet_ntop;
smb_join;
smb_lgrp_add;
smb_lgrp_add_member;
@@ -198,8 +205,6 @@
smb_lgrp_iterate;
smb_lgrp_iterclose;
smb_lgrp_iteropen;
- smb_lgrp_numbydomain;
- smb_lgrp_numbymember;
smb_lgrp_rename;
smb_lgrp_setcmnt;
smb_lgrp_setpriv;
@@ -267,9 +272,13 @@
smb_pwd_iterate = AUXILIARY libsmb_pwd.so;
smb_pwd_iterclose = AUXILIARY libsmb_pwd.so;
smb_pwd_iteropen = AUXILIARY libsmb_pwd.so;
- smb_pwd_num = AUXILIARY libsmb_pwd.so;
smb_pwd_setcntl = AUXILIARY libsmb_pwd.so;
smb_pwd_setpasswd = AUXILIARY libsmb_pwd.so;
+ smb_sam_lookup_name;
+ smb_sam_lookup_sid;
+ smb_sam_grp_cnt;
+ smb_sam_usr_cnt;
+ smb_sam_usr_groups;
smb_setdomainprops;
smb_sid_cmp;
smb_sid_dup;
@@ -294,12 +303,11 @@
smb_update_netlogon_seqnum;
smb_wka_fini;
smb_wka_get_domain;
+ smb_wka_get_sid;
smb_wka_init;
- smb_wka_is_wellknown;
- smb_wka_lookup;
- smb_wka_lookup_domain;
smb_wka_lookup_name;
smb_wka_lookup_sid;
+ smb_wka_token_groups;
smbnative_lm_value;
smbnative_os_value;
smbnative_pdc_value;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c Sun Feb 01 19:44:54 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.
*/
@@ -249,7 +249,7 @@
* domain information.
*/
uint32_t
-smb_get_dcinfo(char *namebuf, uint32_t namebuflen, uint32_t *ipaddr)
+smb_get_dcinfo(char *namebuf, uint32_t namebuflen, smb_inaddr_t *ipaddr)
{
door_arg_t arg;
char *buf;
@@ -285,7 +285,7 @@
if (srvname) {
(void) strlcpy(namebuf, srvname, namebuflen);
if ((h = smb_gethostbyname(srvname, &error_num)) == NULL) {
- *ipaddr = 0;
+ bzero(ipaddr, sizeof (smb_inaddr_t));
} else {
(void) memcpy(ipaddr, h->h_addr, h->h_length);
freehostent(h);
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c Sun Feb 01 19:44:54 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.
*/
@@ -130,7 +130,8 @@
{SMB_CI_KPASSWD_SEQNUM, "kpasswd_seqnum", SCF_TYPE_INTEGER,
0},
{SMB_CI_NETLOGON_SEQNUM, "netlogon_seqnum", SCF_TYPE_INTEGER,
- 0}
+ 0},
+ {SMB_CI_IPV6_ENABLE, "ipv6_enable", SCF_TYPE_BOOLEAN, 0}
/* SMB_CI_MAX */
};
@@ -391,6 +392,24 @@
return (rc);
}
+int
+smb_config_getip(smb_cfg_id_t sc_id, smb_inaddr_t *ipaddr)
+{
+ int rc;
+ char ipstr[INET6_ADDRSTRLEN];
+
+ rc = smb_config_getstr(sc_id, ipstr, sizeof (ipstr));
+ if (rc == SMBD_SMF_OK) {
+ rc = inet_pton(AF_INET, ipstr, ipaddr);
+ if (rc == 0) {
+ rc = inet_pton(AF_INET6, ipstr, ipaddr);
+ if (rc == 0)
+ bzero(ipaddr, sizeof (smb_inaddr_t));
+ }
+ }
+ return (rc);
+}
+
/*
* smb_config_getnum
*
--- a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c Sun Feb 01 19:44:54 2009 -0700
@@ -293,11 +293,20 @@
nt_domain_t *
nt_domain_lookup_name(char *domain_name)
{
+ char nbname[MAXHOSTNAMELEN];
nt_domain_t *domain = nt_domain_list;
+ char *p;
+
+ if (domain_name == NULL || *domain_name == '\0')
+ return (NULL);
+
+ (void) strlcpy(nbname, domain_name, sizeof (nbname));
+ if ((p = strchr(nbname, '.')) != NULL)
+ *p = '\0';
(void) rw_rdlock(&nt_domain_lock);
while (domain) {
- if (utf8_strcasecmp(domain->name, domain_name) == 0)
+ if (utf8_strcasecmp(domain->name, nbname) == 0)
break;
domain = domain->next;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c Sun Feb 01 19:44:54 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.
*/
@@ -285,18 +285,12 @@
idmap_stat stat;
int flag = 0;
- if (!idmaph || !sim || !sid)
+ if (idmaph == NULL || sim == NULL || sid == NULL)
return (IDMAP_ERR_ARG);
- tmpsid = smb_sid_dup(sid);
- if (!tmpsid)
+ if ((tmpsid = smb_sid_split(sid, &sim->sim_rid)) == NULL)
return (IDMAP_ERR_MEMORY);
- if (smb_sid_split(tmpsid, &sim->sim_rid) != 0) {
- smb_sid_free(tmpsid);
- return (IDMAP_ERR_ARG);
- }
-
smb_sid_tostr(tmpsid, sidstr);
sim->sim_domsid = sidstr;
smb_sid_free(tmpsid);
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c Sun Feb 01 19:44:54 2009 -0700
@@ -67,6 +67,7 @@
kcfg->skc_restrict_anon = smb_config_getbool(SMB_CI_RESTRICT_ANON);
kcfg->skc_signing_enable = smb_config_getbool(SMB_CI_SIGNING_ENABLE);
kcfg->skc_signing_required = smb_config_getbool(SMB_CI_SIGNING_REQD);
+ kcfg->skc_ipv6_enable = smb_config_getbool(SMB_CI_IPV6_ENABLE);
kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
kcfg->skc_secmode = smb_config_get_secmode();
@@ -448,11 +449,12 @@
}
int
-smb_get_nameservers(struct in_addr *ips, int sz)
+smb_get_nameservers(smb_inaddr_t *ips, int sz)
{
union res_sockaddr_union set[MAXNS];
int i, cnt;
struct __res_state res_state;
+ char ipstr[INET6_ADDRSTRLEN];
if (ips == NULL)
return (0);
@@ -465,15 +467,23 @@
for (i = 0; i < cnt; i++) {
if (i >= sz)
break;
- ips[i] = set[i].sin.sin_addr;
- syslog(LOG_DEBUG, "NS Found %s name server\n",
- inet_ntoa(ips[i]));
+ ips[i].a_family = AF_INET;
+ bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, INADDRSZ);
+ if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr,
+ INET_ADDRSTRLEN)) {
+ syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
+ continue;
+ }
+ ips[i].a_family = AF_INET6;
+ bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, IPV6_ADDR_LEN);
+ if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr,
+ INET6_ADDRSTRLEN)) {
+ syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
+ }
}
- syslog(LOG_DEBUG, "NS Found %d name servers\n", i);
res_ndestroy(&res_state);
return (i);
}
-
/*
* smb_gethostbyname
*
@@ -492,7 +502,8 @@
struct hostent *h;
h = getipnodebyname(name, AF_INET, 0, err_num);
-
+ if ((h == NULL) || h->h_length != INADDRSZ)
+ h = getipnodebyname(name, AF_INET6, AI_DEFAULT, err_num);
return (h);
}
--- a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c Sun Feb 01 19:44:54 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.
*/
@@ -216,7 +216,7 @@
grp.sg_name = utf8_strlwr(gname);
grp.sg_cmnt = cmnt;
- wka = smb_wka_lookup(gname);
+ wka = smb_wka_lookup_name(gname);
if (wka == NULL) {
if ((pxgrp = getgrnam(gname)) == NULL)
return (SMB_LGRP_NOT_FOUND);
@@ -289,11 +289,11 @@
return (SMB_LGRP_SUCCESS);
/* Cannot rename well-known groups */
- if (smb_wka_is_wellknown(gname))
+ if (smb_wka_lookup_name(gname) != NULL)
return (SMB_LGRP_WKSID);
/* Cannot rename to a well-known groups */
- if (smb_wka_is_wellknown(new_gname))
+ if (smb_wka_lookup_name(new_gname) != NULL)
return (SMB_LGRP_WKSID);
grp.sg_name = new_gname;
@@ -321,7 +321,7 @@
return (SMB_LGRP_INVALID_NAME);
/* Cannot remove a built-in group */
- if (smb_wka_is_wellknown(gname))
+ if (smb_wka_lookup_name(gname) != NULL)
return (SMB_LGRP_WKSID);
db = smb_lgrp_db_open(SMB_LGRP_DB_ORW);
@@ -619,33 +619,6 @@
}
/*
- * smb_lgrp_numbydomain
- *
- * Returns the number of groups which have the given SID
- * as a member.
- */
-int
-smb_lgrp_numbymember(smb_sid_t *msid, int *count)
-{
- smb_giter_t gi;
- smb_group_t grp;
- int rc;
-
- *count = 0;
- rc = smb_lgrp_iteropen(&gi);
- if (rc != SMB_LGRP_SUCCESS)
- return (rc);
-
- while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
- if (smb_lgrp_is_member(&grp, msid))
- (*count)++;
- smb_lgrp_free(&grp);
- }
- smb_lgrp_iterclose(&gi);
- return (SMB_LGRP_SUCCESS);
-}
-
-/*
* smb_lgrp_free
*
* Frees the allocated memory for the fields of the given
@@ -935,7 +908,7 @@
ngrp = sizeof (supported_bg) / sizeof (supported_bg[0]);
for (i = 0; i < ngrp; i++) {
- wka = smb_wka_lookup(supported_bg[i]);
+ wka = smb_wka_lookup_name(supported_bg[i]);
if (wka == NULL)
continue;
rc = smb_lgrp_add(wka->wka_name, wka->wka_desc);
@@ -1636,11 +1609,9 @@
return (SMB_LGRP_SUCCESS);
}
- dom_sid = smb_sid_dup(sid);
- if (dom_sid == NULL)
+ if ((dom_sid = smb_sid_split(sid, rid)) == NULL)
return (SMB_LGRP_NO_MEMORY);
- (void) smb_sid_split(dom_sid, rid);
smb_sid_tostr(dom_sid, sidstr);
free(dom_sid);
--- a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c Sun Feb 01 19:44:54 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.
*/
@@ -124,10 +124,13 @@
static int smb_nic_dbdelhost(const char *);
static int smb_nic_dbsetinfo(sqlite *);
-static int smb_nic_getinfo(char *, smb_nic_t *);
+static int smb_nic_getinfo(char *, smb_nic_t *, int);
static boolean_t smb_nic_nbt_exclude(const smb_nic_t *, const char **, int);
static int smb_nic_nbt_get_exclude_list(char *, char **, int);
+static void smb_close_sockets(int, int);
+static boolean_t smb_duplicate_nic(smb_hostifs_t *iflist, struct lifreq *lifrp);
+
/* This is the list we will monitor */
static smb_niclist_t smb_niclist;
@@ -265,18 +268,11 @@
return (rc);
}
-/*
- * smb_nic_exists
- *
- * Check to see if there's a NIC with the given IP address
- * in the list. Subnet mask will be applied when comparing the
- * IPs if the use_mask arg is true.
- */
boolean_t
-smb_nic_exists(uint32_t ipaddr, boolean_t use_mask)
+smb_nic_exists(smb_inaddr_t *ipaddr, boolean_t use_mask)
{
smb_nic_t *cfg;
- uint32_t mask = 0xFFFFFFFF;
+ uint32_t mask = 0;
int i;
(void) rw_rdlock(&smb_niclist.nl_rwl);
@@ -285,15 +281,12 @@
cfg = &smb_niclist.nl_nics[i];
if (use_mask)
mask = cfg->nic_mask;
-
- if ((ipaddr & mask) == (cfg->nic_ip & mask)) {
+ if (smb_inet_equal(ipaddr, &cfg->nic_ip, mask)) {
(void) rw_unlock(&smb_niclist.nl_rwl);
return (B_TRUE);
}
}
-
(void) rw_unlock(&smb_niclist.nl_rwl);
-
return (B_FALSE);
}
@@ -425,8 +418,12 @@
do {
for (i = 0; i < iflist->if_num; i++) {
ifname = iflist->if_names[i];
- if (smb_nic_getinfo(ifname, nc) < 0)
- continue;
+ if (smb_nic_getinfo(ifname, nc, AF_INET) < 0) {
+ if (smb_nic_getinfo(ifname, nc,
+ AF_INET6) < 0) {
+ continue;
+ }
+ }
(void) strlcpy(nc->nic_host, iflist->if_host,
sizeof (nc->nic_host));
@@ -460,19 +457,16 @@
smb_niclist.nl_cnt = 0;
}
-/*
- * smb_nic_getinfo
- *
- * Get IP info and more for the given interface
- */
static int
-smb_nic_getinfo(char *interface, smb_nic_t *nc)
+smb_nic_getinfo(char *interface, smb_nic_t *nc, int family)
{
struct lifreq lifrr;
- struct sockaddr_in *sa;
int s;
+ boolean_t isv6;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in *sin;
- if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ if ((s = socket(family, SOCK_DGRAM, IPPROTO_IP)) < 0) {
return (-1);
}
@@ -481,28 +475,36 @@
(void) close(s);
return (-1);
}
- sa = (struct sockaddr_in *)&lifrr.lifr_addr;
- nc->nic_ip = (uint32_t)sa->sin_addr.s_addr;
-
- if (nc->nic_ip == 0) {
+ isv6 = (lifrr.lifr_addr.ss_family == AF_INET6);
+ if (isv6) {
+ sin6 = (struct sockaddr_in6 *)(&lifrr.lifr_addr);
+ nc->nic_ip.a_ipv6 = sin6->sin6_addr;
+ nc->nic_ip.a_family = AF_INET6;
+ } else {
+ sin = (struct sockaddr_in *)(&lifrr.lifr_addr);
+ nc->nic_ip.a_ipv4 = (in_addr_t)(sin->sin_addr.s_addr);
+ nc->nic_ip.a_family = AF_INET;
+ }
+ if (smb_inet_iszero(&nc->nic_ip)) {
(void) close(s);
return (-1);
}
-
- if (ioctl(s, SIOCGLIFBRDADDR, &lifrr) < 0) {
- (void) close(s);
- return (-1);
- }
- sa = (struct sockaddr_in *)&lifrr.lifr_broadaddr;
- nc->nic_bcast = (uint32_t)sa->sin_addr.s_addr;
+ /* there is no broadcast or netmask for v6 */
+ if (!isv6) {
+ if (ioctl(s, SIOCGLIFBRDADDR, &lifrr) < 0) {
+ (void) close(s);
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)&lifrr.lifr_broadaddr;
+ nc->nic_bcast = (uint32_t)sin->sin_addr.s_addr;
- if (ioctl(s, SIOCGLIFNETMASK, &lifrr) < 0) {
- (void) close(s);
- return (-1);
+ if (ioctl(s, SIOCGLIFNETMASK, &lifrr) < 0) {
+ (void) close(s);
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)&lifrr.lifr_addr;
+ nc->nic_mask = (uint32_t)sin->sin_addr.s_addr;
}
- sa = (struct sockaddr_in *)&lifrr.lifr_addr;
- nc->nic_mask = (uint32_t)sa->sin_addr.s_addr;
-
if (ioctl(s, SIOCGLIFFLAGS, &lifrr) < 0) {
(void) close(s);
return (-1);
@@ -564,6 +566,15 @@
list_destroy(&hlist->h_list);
}
+static void
+smb_close_sockets(int s4, int s6)
+{
+ if (s4)
+ (void) close(s4);
+ if (s6)
+ (void) close(s6);
+}
+
/*
* smb_nic_hlist_sysget
*
@@ -574,13 +585,14 @@
smb_nic_hlist_sysget(smb_hosts_t *hlist)
{
smb_hostifs_t *iflist;
- struct ifconf ifc;
- struct ifreq ifr;
- struct ifreq *ifrp;
+ struct lifconf lifc;
+ struct lifreq lifrl;
+ struct lifreq *lifrp;
char *ifname;
int ifnum;
int i;
- int s;
+ int s4, s6;
+ struct lifnum lifn;
iflist = malloc(sizeof (smb_hostifs_t));
if (iflist == NULL)
@@ -596,77 +608,102 @@
(void) smb_config_getstr(SMB_CI_SYS_CMNT, iflist->if_cmnt,
sizeof (iflist->if_cmnt));
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if ((s4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
free(iflist);
return (-1);
}
+ s6 = socket(AF_INET6, SOCK_DGRAM, 0);
- if (ioctl(s, SIOCGIFNUM, (char *)&ifnum) < 0) {
- (void) close(s);
+ lifn.lifn_family = AF_UNSPEC;
+ lifn.lifn_flags = 0;
+ if (ioctl(s4, SIOCGLIFNUM, (char *)&lifn) < 0) {
+ smb_close_sockets(s4, s6);
free(iflist);
+ syslog(LOG_ERR, "hlist_sysget: SIOCGLIFNUM errno=%d", errno);
return (-1);
}
- ifc.ifc_len = ifnum * sizeof (struct ifreq);
- ifc.ifc_buf = malloc(ifc.ifc_len);
- if (ifc.ifc_buf == NULL) {
- (void) close(s);
+ lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq);
+ lifc.lifc_buf = malloc(lifc.lifc_len);
+ if (lifc.lifc_buf == NULL) {
+ smb_close_sockets(s4, s6);
free(iflist);
return (-1);
}
- bzero(ifc.ifc_buf, ifc.ifc_len);
+ bzero(lifc.lifc_buf, lifc.lifc_len);
+ lifc.lifc_family = AF_UNSPEC;
+ lifc.lifc_flags = 0;
- if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
- (void) close(s);
+ if (ioctl(s4, SIOCGLIFCONF, (char *)&lifc) < 0) {
+ smb_close_sockets(s4, s6);
free(iflist);
- free(ifc.ifc_buf);
+ free(lifc.lifc_buf);
return (-1);
}
- ifrp = ifc.ifc_req;
- ifnum = ifc.ifc_len / sizeof (struct ifreq);
+ lifrp = lifc.lifc_req;
+ ifnum = lifc.lifc_len / sizeof (struct lifreq);
+ hlist->h_num = 0;
+ for (i = 0; i < ifnum; i++, lifrp++) {
- for (i = 0; i < ifnum; i++, ifrp++) {
+ if ((iflist->if_num > 0) && smb_duplicate_nic(iflist, lifrp))
+ continue;
/*
* Get the flags so that we can skip the loopback interface
*/
- (void) memset(&ifr, 0, sizeof (ifr));
- (void) strlcpy(ifr.ifr_name, ifrp->ifr_name,
- sizeof (ifr.ifr_name));
+ (void) memset(&lifrl, 0, sizeof (lifrl));
+ (void) strlcpy(lifrl.lifr_name, lifrp->lifr_name,
+ sizeof (lifrl.lifr_name));
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- (void) close(s);
- free(ifc.ifc_buf);
- smb_nic_iflist_destroy(iflist);
- return (-1);
+ if (ioctl(s4, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) {
+ if ((s6 < 0) ||
+ (ioctl(s6, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0)) {
+ smb_close_sockets(s4, s6);
+ free(lifc.lifc_buf);
+ smb_nic_iflist_destroy(iflist);
+ return (-1);
+ }
+ }
+ if (lifrl.lifr_flags & IFF_LOOPBACK) {
+ continue;
}
- if (ifr.ifr_flags & IFF_LOOPBACK)
- continue;
-
- if ((ifr.ifr_flags & IFF_UP) == 0)
+ if ((lifrl.lifr_flags & IFF_UP) == 0) {
continue;
-
- ifname = strdup(ifrp->ifr_name);
+ }
+ ifname = strdup(lifrp->lifr_name);
if (ifname == NULL) {
- (void) close(s);
- free(ifc.ifc_buf);
+ smb_close_sockets(s4, s6);
+ free(lifc.lifc_buf);
smb_nic_iflist_destroy(iflist);
return (-1);
}
iflist->if_names[iflist->if_num++] = ifname;
}
-
- (void) close(s);
- free(ifc.ifc_buf);
-
+ hlist->h_ifnum = iflist->if_num;
hlist->h_num = 1;
- hlist->h_ifnum = iflist->if_num;
+ smb_close_sockets(s4, s6);
+ free(lifc.lifc_buf);
list_insert_tail(&hlist->h_list, iflist);
return (0);
}
+static boolean_t
+smb_duplicate_nic(smb_hostifs_t *iflist, struct lifreq *lifrp)
+{
+ int j;
+ /*
+ * throw out duplicate names
+ */
+ for (j = 0; j < iflist->if_num; j++) {
+ if (strcmp(iflist->if_names[j],
+ lifrp->lifr_name) == 0)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
static int
smb_nic_hlist_dbget(smb_hosts_t *hlist)
{
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_sam.c Sun Feb 01 19:44:54 2009 -0700
@@ -0,0 +1,385 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <strings.h>
+#include <smbsrv/libsmb.h>
+
+extern int smb_pwd_num(void);
+extern int smb_lgrp_numbydomain(smb_gdomain_t, int *);
+
+static uint32_t smb_sam_lookup_user(char *, smb_sid_t **);
+static uint32_t smb_sam_lookup_group(char *, smb_sid_t **);
+
+/*
+ * Looks up the given name in local account databases:
+ *
+ * SMB Local users are looked up in /var/smb/smbpasswd
+ * SMB Local groups are looked up in /var/smb/smbgroup.db
+ *
+ * If the account is found, its information is populated
+ * in the passed smb_account_t structure. Caller must free
+ * allocated memories by calling smb_account_free() upon
+ * successful return.
+ *
+ * The type of account is specified by 'type', which can be user,
+ * alias (local group) or unknown. If the caller doesn't know
+ * whether the name is a user or group name then SidTypeUnknown
+ * should be passed.
+ *
+ * If a local user and group have the same name, the user will
+ * always be picked. Note that this situation cannot happen on
+ * Windows systems.
+ *
+ * If a SMB local user/group is found but it turns out that
+ * it'll be mapped to a domain user/group the lookup is considered
+ * failed and NT_STATUS_NONE_MAPPED is returned.
+ *
+ * Return status:
+ *
+ * NT_STATUS_NOT_FOUND This is not a local account
+ * NT_STATUS_NONE_MAPPED It's a local account but cannot be
+ * translated.
+ * other error status codes.
+ */
+uint32_t
+smb_sam_lookup_name(char *domain, char *name, uint16_t type,
+ smb_account_t *account)
+{
+ char hostname[MAXHOSTNAMELEN];
+ smb_sid_t *sid;
+ uint32_t status;
+
+ bzero(account, sizeof (smb_account_t));
+ (void) smb_getnetbiosname(hostname, sizeof (hostname));
+
+ if (domain != NULL) {
+ if (!smb_ishostname(domain))
+ return (NT_STATUS_NOT_FOUND);
+
+ /* Only Netbios hostname is accepted */
+ if (utf8_strcasecmp(domain, hostname) != 0)
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ switch (type) {
+ case SidTypeUser:
+ status = smb_sam_lookup_user(name, &sid);
+ if (status != NT_STATUS_SUCCESS)
+ return (status);
+ break;
+
+ case SidTypeAlias:
+ status = smb_sam_lookup_group(name, &sid);
+ if (status != NT_STATUS_SUCCESS)
+ return (status);
+ break;
+
+ case SidTypeUnknown:
+ type = SidTypeUser;
+ status = smb_sam_lookup_user(name, &sid);
+ if (status == NT_STATUS_SUCCESS)
+ break;
+
+ if (status == NT_STATUS_NONE_MAPPED)
+ return (status);
+
+ type = SidTypeAlias;
+ status = smb_sam_lookup_group(name, &sid);
+ if (status != NT_STATUS_SUCCESS)
+ return (status);
+ break;
+
+ default:
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ account->a_name = strdup(name);
+ account->a_sid = sid;
+ account->a_domain = strdup(hostname);
+ account->a_domsid = smb_sid_split(sid, &account->a_rid);
+ account->a_type = type;
+
+ if (!smb_account_validate(account)) {
+ smb_account_free(account);
+ return (NT_STATUS_NO_MEMORY);
+ }
+
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * Looks up the given SID in local account databases:
+ *
+ * SMB Local users are looked up in /var/smb/smbpasswd
+ * SMB Local groups are looked up in /var/smb/smbgroup.db
+ *
+ * If the account is found, its information is populated
+ * in the passed smb_account_t structure. Caller must free
+ * allocated memories by calling smb_account_free() upon
+ * successful return.
+ *
+ * Return status:
+ *
+ * NT_STATUS_NOT_FOUND This is not a local account
+ * NT_STATUS_NONE_MAPPED It's a local account but cannot be
+ * translated.
+ * other error status codes.
+ */
+uint32_t
+smb_sam_lookup_sid(smb_sid_t *sid, smb_account_t *account)
+{
+ char hostname[MAXHOSTNAMELEN];
+ smb_passwd_t smbpw;
+ smb_group_t grp;
+ uint32_t rid;
+ uid_t id;
+ int id_type;
+ int rc;
+
+ bzero(account, sizeof (smb_account_t));
+
+ if (!smb_sid_islocal(sid))
+ return (NT_STATUS_NOT_FOUND);
+
+ id_type = SMB_IDMAP_UNKNOWN;
+ if (smb_idmap_getid(sid, &id, &id_type) != IDMAP_SUCCESS)
+ return (NT_STATUS_NONE_MAPPED);
+
+ switch (id_type) {
+ case SMB_IDMAP_USER:
+ account->a_type = SidTypeUser;
+ if (smb_pwd_getpwuid(id, &smbpw) == NULL)
+ return (NT_STATUS_NO_SUCH_USER);
+
+ account->a_name = strdup(smbpw.pw_name);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ account->a_type = SidTypeAlias;
+ (void) smb_sid_getrid(sid, &rid);
+ rc = smb_lgrp_getbyrid(rid, SMB_LGRP_LOCAL, &grp);
+ if (rc != SMB_LGRP_SUCCESS)
+ return (NT_STATUS_NO_SUCH_ALIAS);
+
+ account->a_name = strdup(grp.sg_name);
+ smb_lgrp_free(&grp);
+ break;
+
+ default:
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) == 0)
+ account->a_domain = strdup(hostname);
+ account->a_sid = smb_sid_dup(sid);
+ account->a_domsid = smb_sid_split(sid, &account->a_rid);
+
+ if (!smb_account_validate(account)) {
+ smb_account_free(account);
+ return (NT_STATUS_NO_MEMORY);
+ }
+
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * Returns number of SMB users, i.e. users who have entry
+ * in /var/smb/smbpasswd
+ */
+int
+smb_sam_usr_cnt(void)
+{
+ return (smb_pwd_num());
+}
+
+/*
+ * Returns a list of local groups which the given user is
+ * their member. A pointer to an array of smb_ids_t
+ * structure is returned which must be freed by caller.
+ */
+uint32_t
+smb_sam_usr_groups(smb_sid_t *user_sid, smb_ids_t *gids)
+{
+ smb_id_t *ids;
+ smb_giter_t gi;
+ smb_group_t lgrp;
+ int total_cnt, gcnt;
+
+ gcnt = 0;
+ if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
+ return (NT_STATUS_INTERNAL_ERROR);
+
+ while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
+ if (smb_lgrp_is_member(&lgrp, user_sid))
+ gcnt++;
+ smb_lgrp_free(&lgrp);
+ }
+ smb_lgrp_iterclose(&gi);
+
+ if (gcnt == 0)
+ return (NT_STATUS_SUCCESS);
+
+ total_cnt = gids->i_cnt + gcnt;
+ gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
+ if (gids->i_ids == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS)
+ return (NT_STATUS_INTERNAL_ERROR);
+
+ ids = gids->i_ids + gids->i_cnt;
+ while (smb_lgrp_iterate(&gi, &lgrp) == SMB_LGRP_SUCCESS) {
+ if (gcnt == 0) {
+ smb_lgrp_free(&lgrp);
+ break;
+ }
+ if (smb_lgrp_is_member(&lgrp, user_sid)) {
+ ids->i_sid = smb_sid_dup(lgrp.sg_id.gs_sid);
+ if (ids->i_sid == NULL) {
+ smb_lgrp_free(&lgrp);
+ return (NT_STATUS_NO_MEMORY);
+ }
+ ids->i_attrs = lgrp.sg_attr;
+ gids->i_cnt++;
+ gcnt--;
+ ids++;
+ }
+ smb_lgrp_free(&lgrp);
+ }
+ smb_lgrp_iterclose(&gi);
+
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * Returns the number of built-in or local groups stored
+ * in /var/smb/smbgroup.db
+ */
+int
+smb_sam_grp_cnt(nt_domain_type_t dtype)
+{
+ int grpcnt;
+ int rc;
+
+ switch (dtype) {
+ case NT_DOMAIN_BUILTIN:
+ rc = smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &grpcnt);
+ break;
+
+ case NT_DOMAIN_LOCAL:
+ rc = smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &grpcnt);
+ break;
+
+ default:
+ rc = SMB_LGRP_INVALID_ARG;
+ }
+
+ return ((rc == SMB_LGRP_SUCCESS) ? grpcnt : 0);
+}
+
+/*
+ * Determines whether the given SID is a member of the group
+ * specified by gname.
+ */
+boolean_t
+smb_sam_grp_ismember(const char *gname, smb_sid_t *sid)
+{
+ smb_group_t grp;
+ boolean_t ismember = B_FALSE;
+
+ if (smb_lgrp_getbyname((char *)gname, &grp) == SMB_LGRP_SUCCESS) {
+ ismember = smb_lgrp_is_member(&grp, sid);
+ smb_lgrp_free(&grp);
+ }
+
+ return (ismember);
+}
+
+/*
+ * Frees memories allocated for the passed account fields.
+ */
+void
+smb_account_free(smb_account_t *account)
+{
+ free(account->a_name);
+ free(account->a_domain);
+ smb_sid_free(account->a_sid);
+ smb_sid_free(account->a_domsid);
+}
+
+/*
+ * Validates the given account.
+ */
+boolean_t
+smb_account_validate(smb_account_t *account)
+{
+ return ((account->a_name != NULL) && (account->a_sid != NULL) &&
+ (account->a_domain != NULL) && (account->a_domsid != NULL));
+}
+
+/*
+ * Lookup local SMB user account database (/var/smb/smbpasswd)
+ * if there's a match query its SID from idmap service and make
+ * sure the SID is a local SID.
+ *
+ * The memory for the returned SID must be freed by the caller.
+ */
+static uint32_t
+smb_sam_lookup_user(char *name, smb_sid_t **sid)
+{
+ smb_passwd_t smbpw;
+
+ if (smb_pwd_getpwnam(name, &smbpw) == NULL)
+ return (NT_STATUS_NO_SUCH_USER);
+
+ if (smb_idmap_getsid(smbpw.pw_uid, SMB_IDMAP_USER, sid)
+ != IDMAP_SUCCESS)
+ return (NT_STATUS_NONE_MAPPED);
+
+ if (!smb_sid_islocal(*sid)) {
+ smb_sid_free(*sid);
+ return (NT_STATUS_NONE_MAPPED);
+ }
+
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * Lookup local SMB group account database (/var/smb/smbgroup.db)
+ * The memory for the returned SID must be freed by the caller.
+ */
+static uint32_t
+smb_sam_lookup_group(char *name, smb_sid_t **sid)
+{
+ smb_group_t grp;
+
+ if (smb_lgrp_getbyname(name, &grp) != SMB_LGRP_SUCCESS)
+ return (NT_STATUS_NO_SUCH_ALIAS);
+
+ *sid = smb_sid_dup(grp.sg_id.gs_sid);
+ smb_lgrp_free(&grp);
+
+ return ((*sid == NULL) ? NT_STATUS_NO_MEMORY : NT_STATUS_SUCCESS);
+}
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c Sun Feb 01 19:44:54 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.
*/
@@ -362,13 +362,17 @@
* not distinguished syntactically. We check for hosts first because
* it's cheaper (just M*N strcmp()s), then try netgroups.
*
+ * Currently this function always returns B_TRUE for ipv6 until
+ * the underlying functions support ipv6
+ *
* Function returns:
* -1 for "all"
* 0 not found
* 1 found
+ *
*/
int
-smb_chk_hostaccess(ipaddr_t ipaddr, char *access_list)
+smb_chk_hostaccess(smb_inaddr_t *ipaddr, char *access_list)
{
int nentries;
char *gr;
@@ -384,7 +388,10 @@
struct netbuf buf;
struct netconfig *config;
- inaddr.s_addr = (uint32_t)ipaddr;
+ if (ipaddr->a_family == AF_INET6)
+ return (B_TRUE);
+
+ inaddr.s_addr = ipaddr->a_ipv4;
/*
* If no access list - then it's "all"
@@ -395,8 +402,6 @@
nentries = 0;
- /* For now, only IPv4 */
-
sa.sin_family = AF_INET;
sa.sin_port = 0;
sa.sin_addr = inaddr;
--- a/usr/src/lib/smbsrv/libsmb/common/smb_wksids.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_wksids.c Sun Feb 01 19:44:54 2009 -0700
@@ -130,76 +130,21 @@
#define SMB_WKA_NUM (sizeof (wka_tbl)/sizeof (wka_tbl[0]))
/*
- * smb_wka_lookup_sid
- *
- * Search the wka_tbl looking for a match on the specified SID. If the
- * SID matches a builtin entry, the associated name is returned.
- * Otherwise a null pointer is returned.
- */
-char *
-smb_wka_lookup_sid(smb_sid_t *sid, uint16_t *sid_name_use)
-{
- smb_wka_t *entry;
- int i;
-
- for (i = 0; i < SMB_WKA_NUM; ++i) {
- entry = &wka_tbl[i];
-
- if (smb_sid_cmp(sid, entry->wka_binsid)) {
- if (sid_name_use)
- *sid_name_use = entry->wka_type;
- return (entry->wka_name);
- }
- }
-
- return (NULL);
-}
-
-
-/*
- * smb_wka_lookup_name
- *
- * Search the wka_tbl looking for a match on the specified name. If the
- * name matches a builtin entry, the associated SID (which is in
- * malloc'd memory) is returned. Otherwise a null pointer is returned.
- */
-smb_sid_t *
-smb_wka_lookup_name(char *name, uint16_t *sid_name_use)
-{
- smb_wka_t *entry;
- int i;
-
- for (i = 0; i < SMB_WKA_NUM; ++i) {
- entry = &wka_tbl[i];
-
- if (!utf8_strcasecmp(name, entry->wka_name)) {
- if (sid_name_use)
- *sid_name_use = entry->wka_type;
- return (smb_sid_dup(entry->wka_binsid));
- }
- }
-
- return (NULL);
-}
-
-/*
- * smb_wka_lookup
- *
- * Search the wka_tbl looking for a match on the specified name. If the
- * name matches a builtin entry then pointer to that entry will be
- * returned. Otherwise 0 is returned.
+ * Looks up well known accounts table for the given SID.
+ * Upon success returns a pointer to the account entry in
+ * the table, otherwise returns NULL.
*/
smb_wka_t *
-smb_wka_lookup(char *name)
+smb_wka_lookup_sid(smb_sid_t *sid)
{
smb_wka_t *entry;
int i;
(void) rw_rdlock(&wk_rwlock);
+
for (i = 0; i < SMB_WKA_NUM; ++i) {
entry = &wka_tbl[i];
-
- if (!utf8_strcasecmp(name, entry->wka_name)) {
+ if (smb_sid_cmp(sid, entry->wka_binsid)) {
(void) rw_unlock(&wk_rwlock);
return (entry);
}
@@ -211,42 +156,43 @@
/*
- * smb_wka_is_wellknown
- *
- * Search the wka_tbl looking for a match on the specified name. If the
- * name matches a builtin entry returns 1. Otherwise returns 0.
+ * Looks up well known accounts table for the given name.
+ * Upon success returns a pointer to the binary SID of the
+ * entry, otherwise returns NULL.
*/
-boolean_t
-smb_wka_is_wellknown(char *name)
+smb_sid_t *
+smb_wka_get_sid(char *name)
{
- int i;
+ smb_wka_t *entry;
+ smb_sid_t *sid = NULL;
- for (i = 0; i < SMB_WKA_NUM; ++i) {
- if (utf8_strcasecmp(name, wka_tbl[i].wka_name) == 0)
- return (B_TRUE);
- }
+ if ((entry = smb_wka_lookup_name(name)) != NULL)
+ sid = entry->wka_binsid;
- return (B_FALSE);
+ return (sid);
}
/*
- * smb_wka_lookup_domain
- *
- * Return the builtin domain name for the specified alias or group name.
+ * Looks up well known accounts table for the given name.
+ * Upon success returns a pointer to the account entry in
+ * the table, otherwise returns NULL.
*/
-char *
-smb_wka_lookup_domain(char *name)
+smb_wka_t *
+smb_wka_lookup_name(char *name)
{
smb_wka_t *entry;
int i;
+ (void) rw_rdlock(&wk_rwlock);
for (i = 0; i < SMB_WKA_NUM; ++i) {
entry = &wka_tbl[i];
-
- if (!utf8_strcasecmp(name, entry->wka_name))
- return (wka_nbdomain[entry->wka_domidx]);
+ if (!utf8_strcasecmp(name, entry->wka_name)) {
+ (void) rw_unlock(&wk_rwlock);
+ return (entry);
+ }
}
+ (void) rw_unlock(&wk_rwlock);
return (NULL);
}
@@ -262,6 +208,33 @@
return (NULL);
}
+uint32_t
+smb_wka_token_groups(boolean_t isadmin, smb_ids_t *gids)
+{
+ static char *grps[] =
+ {"Authenticated Users", "NETWORK", "Administrators"};
+ smb_id_t *id;
+ int gcnt, i;
+ int total_cnt;
+
+ gcnt = (isadmin) ? 3 : 2;
+ total_cnt = gids->i_cnt + gcnt;
+
+ gids->i_ids = realloc(gids->i_ids, total_cnt * sizeof (smb_id_t));
+ if (gids->i_ids == NULL)
+ return (NT_STATUS_NO_MEMORY);
+
+ id = gids->i_ids + gids->i_cnt;
+ for (i = 0; i < gcnt; i++, gids->i_cnt++, id++) {
+ id->i_sid = smb_sid_dup(smb_wka_get_sid(grps[i]));
+ id->i_attrs = 0x7;
+ if (id->i_sid == NULL)
+ return (NT_STATUS_NO_MEMORY);
+ }
+
+ return (NT_STATUS_SUCCESS);
+}
+
/*
* smb_wka_init
*
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c Sun Feb 01 19:44:54 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.
*/
@@ -100,9 +100,17 @@
* Length of "dc=" prefix.
*/
#define SMB_ADS_DN_PREFIX_LEN 3
-
#define SMB_ADS_MSDCS_SVC_CNT 2
+static char *smb_ads_computer_objcls[] = {
+ "top", "person", "organizationalPerson",
+ "user", "computer", NULL
+};
+
+static char *smb_ads_share_objcls[] = {
+ "top", "leaf", "connectionPoint", "volume", NULL
+};
+
/* Cached ADS server to communicate with */
static smb_ads_host_info_t *smb_ads_cached_host_info = NULL;
static mutex_t smb_ads_cached_host_mtx;
@@ -240,13 +248,10 @@
static int
smb_ads_ldap_ping(smb_ads_host_info_t *ads_host)
{
- struct in_addr addr;
int ldversion = LDAP_VERSION3, status, timeoutms = 5 * 1000;
LDAP *ld = NULL;
- addr.s_addr = ads_host->ip_addr;
-
- ld = ldap_init((char *)inet_ntoa(addr), ads_host->port);
+ ld = ldap_init(ads_host->name, ads_host->port);
if (ld == NULL)
return (-1);
@@ -446,9 +451,10 @@
uchar_t *eom, uchar_t *buf, smb_ads_host_info_t *ads_host_list)
{
int i, j, len;
- in_addr_t ipaddr;
+ smb_inaddr_t ipaddr;
char hostname[MAXHOSTNAMELEN];
char *name;
+ uint16_t size = 0;
for (i = 0; i < addit_cnt; i++) {
@@ -460,10 +466,25 @@
*ptr += len;
/* skip type, class, TTL, data len */
- *ptr += 10;
-
+ *ptr += 8;
/* LINTED: E_CONSTANT_CONDITION */
- NS_GET32(ipaddr, *ptr);
+ NS_GET16(size, *ptr);
+
+ if (size == INADDRSZ) {
+ /* LINTED: E_CONSTANT_CONDITION */
+ NS_GET32(ipaddr.a_ipv4, *ptr);
+ ipaddr.a_ipv4 = htonl(ipaddr.a_ipv4);
+ ipaddr.a_family = AF_INET;
+ } else if (size == IN6ADDRSZ) {
+#ifdef BIG_ENDIAN
+ bcopy(*ptr, &ipaddr.a_ipv6, IN6ADDRSZ);
+#else
+ for (i = 0; i < IN6ADDRSZ; i++)
+ (uint8_t *)(ipaddr.a_ipv6)
+ [IN6ADDRSZ-1-i] = *(*ptr+i);
+#endif
+ ipaddr.a_family = AF_INET6;
+ }
/*
* find the host in the list of DC records from
@@ -473,12 +494,11 @@
for (j = 0; j < ans_cnt; j++) {
if ((name = ads_host_list[j].name) == NULL)
continue;
-
- if (utf8_strcasecmp(name, hostname) == 0)
- ads_host_list[j].ip_addr = htonl(ipaddr);
+ if (utf8_strcasecmp(name, hostname) == 0) {
+ ads_host_list[j].ipaddr = ipaddr;
+ }
}
}
-
return (0);
}
@@ -691,12 +711,25 @@
struct hostent *h;
int error;
- h = getipnodebyname(hentry->name, AF_INET, 0, &error);
- if (h == NULL || h->h_addr == NULL)
+ switch (hentry->ipaddr.a_family) {
+ case AF_INET6:
+ h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
+ AI_DEFAULT, &error);
+ if (h == NULL || h->h_length != IPV6_ADDR_LEN)
+ return (-1);
+ break;
+
+ case AF_INET:
+ h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
+ 0, &error);
+ if (h == NULL || h->h_length != INADDRSZ)
+ return (-1);
+ break;
+
+ default:
return (-1);
-
- (void) memcpy(&hentry->ip_addr, h->h_addr, h->h_length);
-
+ }
+ bcopy(*(h->h_addr_list), &hentry->ipaddr.a_ip, h->h_length);
freehostent(h);
return (0);
}
@@ -778,9 +811,8 @@
hlistp = hlist->ah_list;
for (i = 0; i < hlist->ah_cnt; i++) {
-
/* Do a host lookup by hostname to get the IP address */
- if (hlistp[i].ip_addr == 0) {
+ if (smb_inet_iszero(&hlistp[i].ipaddr)) {
if (smb_ads_getipnodebyname(&hlistp[i]) < 0)
continue;
}
@@ -940,20 +972,17 @@
LDAP *ld;
int version = 3;
smb_ads_host_info_t *ads_host = NULL;
- struct in_addr addr;
ads_host = smb_ads_find_host(domain, NULL);
if (ads_host == NULL)
return (NULL);
-
ah = (smb_ads_handle_t *)malloc(sizeof (smb_ads_handle_t));
if (ah == NULL)
return (NULL);
(void) memset(ah, 0, sizeof (smb_ads_handle_t));
- addr.s_addr = ads_host->ip_addr;
- if ((ld = ldap_init((char *)inet_ntoa(addr), ads_host->port)) == NULL) {
+ if ((ld = ldap_init(ads_host->name, ads_host->port)) == NULL) {
smb_ads_free_cached_host();
free(ah);
return (NULL);
@@ -1454,10 +1483,10 @@
const char *unc_name, const char *adsContainer)
{
LDAPMod *attrs[SMB_ADS_SHARE_NUM_ATTR];
- char *tmp1[5], *tmp2[5];
int j = 0;
char *share_dn;
int len, ret;
+ char *unc_names[] = {(char *)unc_name, NULL};
len = 5 + strlen(adsShareName) + strlen(adsContainer) +
strlen(ah->domain_dn) + 1;
@@ -1476,18 +1505,11 @@
attrs[j]->mod_op = LDAP_MOD_ADD;
attrs[j]->mod_type = "objectClass";
- tmp1[0] = "top";
- tmp1[1] = "leaf";
- tmp1[2] = "connectionPoint";
- tmp1[3] = "volume";
- tmp1[4] = 0;
- attrs[j]->mod_values = tmp1;
+ attrs[j]->mod_values = smb_ads_share_objcls;
attrs[++j]->mod_op = LDAP_MOD_ADD;
attrs[j]->mod_type = "uNCName";
- tmp2[0] = (char *)unc_name;
- tmp2[1] = 0;
- attrs[j]->mod_values = tmp2;
+ attrs[j]->mod_values = unc_names;
if ((ret = ldap_add_s(ah->ld, share_dn, attrs)) != LDAP_SUCCESS) {
smb_tracef("smbns_ads: %s: ldap_add error: %s",
@@ -1890,7 +1912,7 @@
smb_ads_computer_op(smb_ads_handle_t *ah, int op, int dclevel, char *dn)
{
LDAPMod *attrs[SMB_ADS_COMPUTER_NUM_ATTR];
- char *oc_vals[6], *sam_val[2], *usr_val[2];
+ char *sam_val[2], *usr_val[2];
char *spn_set[SMBKRB5_SPN_IDX_MAX + 1], *ctl_val[2], *fqh_val[2];
char *encrypt_val[2];
int j = -1;
@@ -1939,13 +1961,7 @@
if (op == LDAP_MOD_ADD) {
attrs[++j]->mod_op = op;
attrs[j]->mod_type = "objectClass";
- oc_vals[0] = "top";
- oc_vals[1] = "person";
- oc_vals[2] = "organizationalPerson";
- oc_vals[3] = "user";
- oc_vals[4] = "computer";
- oc_vals[5] = 0;
- attrs[j]->mod_values = oc_vals;
+ attrs[j]->mod_values = smb_ads_computer_objcls;
}
attrs[++j]->mod_op = op;
@@ -2226,38 +2242,29 @@
* Modify the user account control attribute of an existing computer
* object on AD.
*
- * Returns 0 on success. Otherwise, returns -1.
+ * Returns LDAP error code.
*/
static int
-smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *ah, int des_only, char *dn)
+smb_ads_update_computer_cntrl_attr(smb_ads_handle_t *ah, int flags, char *dn)
{
LDAPMod *attrs[2];
char *ctl_val[2];
- int ret, usrctl_flags = 0;
+ int ret = 0;
char usrctl_buf[16];
if (smb_ads_alloc_attr(attrs, sizeof (attrs) / sizeof (LDAPMod *)) != 0)
- return (-1);
+ return (LDAP_NO_MEMORY);
attrs[0]->mod_op = LDAP_MOD_REPLACE;
attrs[0]->mod_type = SMB_ADS_ATTR_CTL;
- usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
- SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION |
- SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
-
- if (des_only)
- usrctl_flags |= SMB_ADS_USER_ACCT_CTL_USE_DES_KEY_ONLY;
-
- (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", usrctl_flags);
+ (void) snprintf(usrctl_buf, sizeof (usrctl_buf), "%d", flags);
ctl_val[0] = usrctl_buf;
ctl_val[1] = 0;
attrs[0]->mod_values = ctl_val;
-
if ((ret = ldap_modify_s(ah->ld, dn, attrs)) != LDAP_SUCCESS) {
smb_tracef("smbns_ads: ldap_modify error: %s",
ldap_err2string(ret));
- ret = -1;
}
smb_ads_free_attr(attrs);
@@ -2355,7 +2362,7 @@
boolean_t des_only, delete = B_TRUE;
smb_adjoin_status_t rc = SMB_ADJOIN_SUCCESS;
boolean_t new_acct;
- int dclevel, num;
+ int dclevel, num, usrctl_flags = 0;
smb_ads_qstat_t qstat;
char dn[SMB_ADS_DN_MAX];
char *tmpfile;
@@ -2448,7 +2455,31 @@
kvno = smb_ads_lookup_computer_attr_kvno(ah, dn);
- if (smb_ads_update_computer_cntrl_attr(ah, des_only, dn)
+ /*
+ * Only members of Domain Admins and Enterprise Admins can set
+ * the TRUSTED_FOR_DELEGATION userAccountControl flag.
+ */
+ if (smb_ads_update_computer_cntrl_attr(ah,
+ SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION, dn)
+ == LDAP_INSUFFICIENT_ACCESS) {
+ usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
+ SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
+
+ syslog(LOG_NOTICE, "smbns_ads: Unable to set the "
+ "TRUSTED_FOR_DELEGATION userAccountControl flag on "
+ "the machine account in Active Directory. Please refer "
+ "to the Troubleshooting guide for more information.");
+
+ } else {
+ usrctl_flags |= (SMB_ADS_USER_ACCT_CTL_WKSTATION_TRUST_ACCT |
+ SMB_ADS_USER_ACCT_CTL_TRUSTED_FOR_DELEGATION |
+ SMB_ADS_USER_ACCT_CTL_DONT_EXPIRE_PASSWD);
+ }
+
+ if (des_only)
+ usrctl_flags |= SMB_ADS_USER_ACCT_CTL_USE_DES_KEY_ONLY;
+
+ if (smb_ads_update_computer_cntrl_attr(ah, usrctl_flags, dn)
!= 0) {
rc = SMB_ADJOIN_ERR_UPDATE_CNTRL_ATTR;
goto adjoin_cleanup;
@@ -2524,30 +2555,6 @@
}
/*
- * smb_ads_get_pdc_ip
- *
- * Check to see if there is any configured PDC.
- * If there is then converts the string IP to
- * integer format and returns it.
- */
-static uint32_t
-smb_ads_get_pdc_ip(void)
-{
- char p[INET_ADDRSTRLEN];
- uint32_t ipaddr = 0;
- int rc;
-
- rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, p, sizeof (p));
- if (rc == SMBD_SMF_OK) {
- rc = inet_pton(AF_INET, p, &ipaddr);
- if (rc == 0)
- ipaddr = 0;
- }
-
- return (ipaddr);
-}
-
-/*
* smb_ads_select_pdc
*
* This method walks the list of DCs and returns the first DC record that
@@ -2561,17 +2568,17 @@
smb_ads_select_pdc(smb_ads_host_list_t *hlist)
{
smb_ads_host_info_t *hentry;
- uint32_t ip;
+ smb_inaddr_t ipaddr;
size_t cnt;
int i;
- if ((ip = smb_ads_get_pdc_ip()) == 0)
+ if (smb_config_getip(SMB_CI_DOMAIN_SRV, &ipaddr) != SMBD_SMF_OK)
return (NULL);
cnt = hlist->ah_cnt;
for (i = 0; i < cnt; i++) {
hentry = &hlist->ah_list[i];
- if ((hentry->ip_addr == ip) &&
+ if (smb_inet_equal(&hentry->ipaddr, &ipaddr, SMB_INET_NOMASK) &&
(smb_ads_ldap_ping(hentry) == 0))
return (hentry);
}
@@ -2605,10 +2612,15 @@
for (i = 0; i < cnt; i++) {
hentry = &hlist->ah_list[i];
- if ((hentry->ip_addr & lnic->nic_mask) ==
- (lnic->nic_ip & lnic->nic_mask))
- if (smb_ads_ldap_ping(hentry) == 0)
- return (hentry);
+ if ((hentry->ipaddr.a_family == AF_INET) &&
+ (lnic->nic_ip.a_family == AF_INET)) {
+ if ((hentry->ipaddr.a_ipv4 &
+ lnic->nic_mask) ==
+ (lnic->nic_ip.a_ipv4 &
+ lnic->nic_mask))
+ if (smb_ads_ldap_ping(hentry) == 0)
+ return (hentry);
+ }
}
} while (smb_nic_getnext(&ni) == 0);
@@ -2735,8 +2747,8 @@
{
smb_ads_host_info_t *hinfo = NULL;
char *p;
- struct in_addr addr;
char *sought_host;
+ char ipstr[INET6_ADDRSTRLEN];
if (!fqdn || !buf)
return (B_FALSE);
@@ -2746,9 +2758,9 @@
if ((hinfo = smb_ads_find_host(fqdn, sought_host)) == NULL)
return (B_FALSE);
- addr.s_addr = hinfo->ip_addr;
- syslog(LOG_DEBUG, "msdcsLookupADS: %s [%s]", hinfo->name,
- inet_ntoa(addr));
+ smb_tracef("msdcsLookupADS: %s [%s]", hinfo->name,
+ smb_inet_ntop(&hinfo->ipaddr, ipstr,
+ SMB_IPSTRLEN(hinfo->ipaddr.a_family)));
(void) strlcpy(buf, hinfo->name, buflen);
/*
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.h Sun Feb 01 19:44:54 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.
*/
@@ -71,7 +71,7 @@
int port; /* ldap port */
int priority; /* DNS SRV record priority */
int weight; /* DNS SRV record weight */
- in_addr_t ip_addr; /* network byte order */
+ smb_inaddr_t ipaddr; /* network byte order */
} smb_ads_host_info_t;
typedef struct smb_ads_host_list {
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c Sun Feb 01 19:44:54 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.
*/
@@ -661,7 +661,7 @@
if (hinfo->hi_nic.nic_smbflags & SMB_NICF_ALIAS)
return (-1);
- ipaddr = hinfo->hi_nic.nic_ip;
+ ipaddr = hinfo->hi_nic.nic_ip.a_ipv4;
mask = hinfo->hi_nic.nic_mask;
*result = *name;
@@ -869,7 +869,8 @@
(void) rw_rdlock(&smb_binfo.bi_hlist_rwl);
hinfo = list_head(&smb_binfo.bi_hlist);
while (hinfo) {
- if ((hinfo->hi_nic.nic_ip & hinfo->hi_nic.nic_mask) ==
+ if ((hinfo->hi_nic.nic_ip.a_ipv4 &
+ hinfo->hi_nic.nic_mask) ==
(datagram->src.addr_list.sin.sin_addr.s_addr &
hinfo->hi_nic.nic_mask)) {
h_found = B_TRUE;
@@ -1072,8 +1073,9 @@
hinfo = list_head(&smb_binfo.bi_hlist);
while (hinfo) {
smb_init_name_struct((unsigned char *)resource_domain, 0x00, 0,
- hinfo->hi_nic.nic_ip, htons(DGM_SRVC_UDP_PORT),
- NAME_ATTR_GROUP, NAME_ATTR_LOCAL, &name);
+ hinfo->hi_nic.nic_ip.a_ipv4,
+ htons(DGM_SRVC_UDP_PORT), NAME_ATTR_GROUP,
+ NAME_ATTR_LOCAL, &name);
(void) smb_name_add_name(&name);
hinfo = list_next(&smb_binfo.bi_hlist, hinfo);
@@ -1157,11 +1159,11 @@
(void) strlcpy(hinfo->hi_nbname, hinfo->hi_nic.nic_host,
NETBIOS_NAME_SZ);
(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, htons(DGM_SRVC_UDP_PORT),
- NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &hinfo->hi_netname);
+ 0x20, 0, hinfo->hi_nic.nic_ip.a_ipv4,
+ htons(DGM_SRVC_UDP_PORT), NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL,
+ &hinfo->hi_netname);
list_insert_tail(&smb_binfo.bi_hlist, hinfo);
smb_binfo.bi_hcnt++;
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c Sun Feb 01 19:44:54 2009 -0700
@@ -111,6 +111,7 @@
static void dyndns_msgid_init(void);
static int dyndns_get_msgid(void);
static void dyndns_syslog(int, int, const char *);
+static int dyndns_getnameinfo(smb_inaddr_t *, char *, int, int);
int
dyndns_start(void)
@@ -500,6 +501,9 @@
return (buf);
}
+
+
+
static char *
dyndns_put_int(char *buf, int val)
{
@@ -508,6 +512,15 @@
return (buf);
}
+static char *
+dyndns_put_v6addr(char *buf, smb_inaddr_t *val)
+{
+
+ val->a_family = AF_INET6;
+ (void) memcpy(buf, &val->a_ipv6, IN6ADDRSZ);
+ buf += IN6ADDRSZ;
+ return (buf);
+}
/*
* dyndns_stuff_str
* Converts a domain string by removing periods and replacing with a byte value
@@ -663,22 +676,28 @@
{
char *namePtr;
int rec_len, data_len;
+ smb_inaddr_t ipaddr;
+ int isv4 = 1;
rec_len = strlen(name) + 10;
+ if (inet_pton(AF_INET, data, &ipaddr) == 1)
+ isv4 = 1;
+ else if (inet_pton(AF_INET6, data, &ipaddr) == 1)
+ isv4 = 0;
+
if (add_del == UPDATE_ADD) {
if (forw_rev == UPDATE_FORW)
- data_len = 4;
+ data_len = isv4 ? 4 : 16;
else
data_len = strlen(data) + 2;
} else {
if (del_type == DEL_ALL)
data_len = 0;
else if (forw_rev == UPDATE_FORW)
- data_len = 4;
+ data_len = isv4 ? 4 : 16;
else
data_len = strlen(data) + 2;
}
-
if (rec_len + data_len > buf_len) {
syslog(LOG_ERR, "dyndns update section: buffer too small");
return (-1);
@@ -687,7 +706,10 @@
namePtr = *ptr;
(void) dyndns_stuff_str(&namePtr, name);
*ptr = namePtr;
- *ptr = dyndns_put_nshort(*ptr, type);
+ if (isv4)
+ *ptr = dyndns_put_nshort(*ptr, type);
+ else
+ *ptr = dyndns_put_nshort(*ptr, ns_t_aaaa);
*ptr = dyndns_put_nshort(*ptr, class);
*ptr = dyndns_put_nlong(*ptr, ttl);
@@ -697,8 +719,13 @@
}
if (forw_rev == UPDATE_FORW) {
- *ptr = dyndns_put_nshort(*ptr, 4);
- *ptr = dyndns_put_int(*ptr, inet_addr(data)); /* ip address */
+ if (isv4) {
+ *ptr = dyndns_put_nshort(*ptr, 4);
+ *ptr = dyndns_put_int(*ptr, ipaddr.a_ipv4);
+ } else {
+ *ptr = dyndns_put_nshort(*ptr, 16);
+ *ptr = dyndns_put_v6addr(*ptr, &ipaddr);
+ }
} else {
*ptr = dyndns_put_nshort(*ptr, strlen(data)+2);
namePtr = *ptr;
@@ -848,44 +875,69 @@
* descriptor: descriptor referencing the created socket
* -1 : error
*/
+
static int
-dyndns_open_init_socket(int sock_type, unsigned long dest_addr, int port)
+dyndns_open_init_socket(int sock_type, smb_inaddr_t *dest_addr, int port)
{
int s;
struct sockaddr_in my_addr;
+ struct sockaddr_in6 my6_addr;
struct sockaddr_in serv_addr;
-
- if ((s = socket(AF_INET, sock_type, 0)) == -1) {
- syslog(LOG_ERR, "dyndns: socket error");
- return (-1);
- }
+ struct sockaddr_in6 serv6_addr;
+ int family;
- bzero(&my_addr, sizeof (my_addr));
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(0);
- my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ family = dest_addr->a_family;
- if (bind(s, (struct sockaddr *)&my_addr, sizeof (my_addr)) < 0) {
- syslog(LOG_ERR, "dyndns: client bind error");
- (void) close(s);
+ if ((s = socket(family, sock_type, 0)) == -1) {
+ syslog(LOG_ERR, "dyndns: socket error\n");
return (-1);
}
-
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
- serv_addr.sin_addr.s_addr = dest_addr;
-
- if (connect(s, (struct sockaddr *)&serv_addr,
- sizeof (struct sockaddr_in)) < 0) {
- syslog(LOG_ERR, "dyndns: client connect error (%s)",
- strerror(errno));
- (void) close(s);
- return (-1);
+ if (family == AF_INET) {
+ bzero(&my_addr, sizeof (my_addr));
+ my_addr.sin_family = family;
+ my_addr.sin_port = htons(0);
+ my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ if (bind(s, (struct sockaddr *)&my_addr,
+ sizeof (my_addr)) < 0) {
+ syslog(LOG_ERR, "dyndns: client bind err\n");
+ (void) close(s);
+ return (-1);
+ }
+ serv_addr.sin_family = family;
+ serv_addr.sin_port = htons(port);
+ serv_addr.sin_addr.s_addr = dest_addr->a_ipv4;
+ if (connect(s, (struct sockaddr *)&serv_addr,
+ sizeof (struct sockaddr_in)) < 0) {
+ syslog(LOG_ERR, "dyndns: client connect (%s)\n",
+ strerror(errno));
+ (void) close(s);
+ return (-1);
+ }
+ } else {
+ bzero(&my6_addr, sizeof (my6_addr));
+ my6_addr.sin6_family = family;
+ my6_addr.sin6_port = htons(0);
+ bzero(&my6_addr.sin6_addr.s6_addr, IN6ADDRSZ);
+ if (bind(s, (struct sockaddr *)&my6_addr,
+ sizeof (my6_addr)) < 0) {
+ syslog(LOG_ERR, "dyndns: client bind err\n");
+ (void) close(s);
+ return (-1);
+ }
+ serv6_addr.sin6_family = family;
+ serv6_addr.sin6_port = htons(port);
+ bcopy(&serv6_addr.sin6_addr.s6_addr, &dest_addr->a_ipv6,
+ IN6ADDRSZ);
+ if (connect(s, (struct sockaddr *)&serv6_addr,
+ sizeof (struct sockaddr_in6)) < 0) {
+ syslog(LOG_ERR, "dyndns: client connect err (%s)\n",
+ strerror(errno));
+ (void) close(s);
+ return (-1);
+ }
}
-
return (s);
}
-
/*
* dyndns_build_tkey_msg
* This routine is used to build the TKEY message to transmit GSS tokens
@@ -1106,27 +1158,24 @@
* -1: error
* 0: success
*/
+
static gss_ctx_id_t
-dyndns_get_sec_context(const char *hostname, int dns_ip)
+dyndns_get_sec_context(const char *hostname, smb_inaddr_t *dns_ip)
{
int s;
gss_cred_id_t cred_handle;
gss_ctx_id_t gss_context;
gss_OID oid;
- struct hostent *hentry;
char *key_name, dns_hostname[MAXHOSTNAMELEN];
cred_handle = GSS_C_NO_CREDENTIAL;
oid = GSS_C_NO_OID;
key_name = (char *)hostname;
- hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET);
- if (hentry == NULL) {
- syslog(LOG_ERR, "dyndns gethostbyaddr failed");
+ if (dyndns_getnameinfo(dns_ip, dns_hostname,
+ sizeof (dns_hostname), 0)) {
return (NULL);
}
- (void) strcpy(dns_hostname, hentry->h_name);
-
if ((s = dyndns_open_init_socket(SOCK_STREAM, dns_ip, 53)) < 0) {
return (NULL);
}
@@ -1139,6 +1188,33 @@
return (gss_context);
}
+static int
+dyndns_getnameinfo(smb_inaddr_t *dns_ip, char *dns_hostname,
+ int hostlen, int flags)
+{
+ socklen_t salen;
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in sin;
+ void *sp;
+
+ if (dns_ip->a_family == AF_INET) {
+ salen = sizeof (struct sockaddr_in);
+ sin.sin_family = dns_ip->a_family;
+ sin.sin_port = 0;
+ sin.sin_addr.s_addr = dns_ip->a_ipv4;
+ sp = &sin;
+ } else {
+ salen = sizeof (struct sockaddr_in6);
+ sin6.sin6_family = dns_ip->a_family;
+ sin6.sin6_port = 0;
+ (void) memcpy(&sin6.sin6_addr.s6_addr, &dns_ip->a_ipv6,
+ sizeof (sin6.sin6_addr.s6_addr));
+ sp = &sin6;
+ }
+ return (getnameinfo((struct sockaddr *)sp, salen,
+ dns_hostname, hostlen, NULL, 0, flags));
+}
+
/*
* dyndns_build_add_remove_msg
* This routine builds the update request message for adding and removing DNS
@@ -1185,6 +1261,9 @@
char *zone, *resource, *data, zone_buf[100], resrc_buf[100];
int zoneType, zoneClass, type, class, ttl;
char *p;
+ smb_inaddr_t tmp_addr;
+ int i, j, k;
+ int fourcnt;
queryReq = REQ_UPDATE;
zoneCount = 1;
@@ -1220,26 +1299,54 @@
resource = (char *)hostname;
data = (char *)ip_addr;
} else {
- (void) sscanf(ip_addr, "%d.%d.%d.%d", &a, &b, &c, &d);
- (void) sprintf(zone_buf, "%d.%d.%d.in-addr.arpa", c, b, a);
- zone = p = zone_buf;
+ if (inet_pton(AF_INET, ip_addr, &tmp_addr) == 1) {
+ (void) sscanf(ip_addr, "%d.%d.%d.%d", &a, &b, &c, &d);
+ (void) sprintf(zone_buf, "%d.%d.%d.in-addr.arpa",
+ c, b, a);
+ zone = p = zone_buf;
- /* Try higher domains according to the level requested */
- while (--level >= 0) {
- /* domain */
- if ((zone = (char *)strchr(p, '.')) == NULL) {
- return (-1);
+ /* Try higher domains based on level requested */
+ while (--level >= 0) {
+ /* domain */
+ if ((zone = (char *)strchr(p, '.')) == NULL) {
+ return (-1);
+ }
+ zone += 1;
+ p = zone;
}
- zone += 1;
- p = zone;
+ (void) sprintf(resrc_buf, "%d.%d.%d.%d.in-addr.arpa",
+ d, c, b, a);
+ } else {
+ /*
+ * create reverse nibble ipv6 format
+ */
+ bzero(resrc_buf, 100);
+ i = 0;
+ j = 0;
+ while (ip_addr[i] != 0)
+ i++;
+ i--;
+ while (i >= 0) {
+ fourcnt = 3;
+ while ((i >= 0) && (ip_addr[i] != ':')) {
+ resrc_buf[j++] = ip_addr[i];
+ (void) strcat(&resrc_buf[j++], ".");
+ fourcnt --;
+ i--;
+ }
+ for (k = 0; k <= fourcnt; k++) {
+ resrc_buf[j++] = '0';
+ (void) strcat(&resrc_buf[j++], ".");
+ }
+ i--;
+ }
+ (void) strcat(resrc_buf, "ip6.arpa");
+ (void) strcpy(zone_buf, &resrc_buf[32]);
+ zone = zone_buf;
}
-
- (void) sprintf(resrc_buf, "%d.%d.%d.%d.in-addr.arpa",
- d, c, b, a);
resource = resrc_buf; /* ip info */
data = (char *)hostname;
}
-
if (dyndns_build_quest_zone(&bufptr, BUFLEN_UDP(bufptr, buf), zone,
zoneType, zoneClass) == -1) {
return (-1);
@@ -1393,13 +1500,14 @@
* rec_buf: reply dat
* 0 : success
*/
+
static int
dyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf)
{
int i, retval, addr_len;
struct timeval tv, timeout;
fd_set rfds;
- struct sockaddr_in from_addr;
+ struct sockaddr_in6 from_addr;
timeout.tv_usec = 0;
timeout.tv_sec = DYNDNS_QUERY_TIMEOUT;
@@ -1422,11 +1530,10 @@
return (-1);
} else if (retval > 0) {
bzero(rec_buf, NS_PACKETSZ);
- /* required by recvfrom */
- addr_len = sizeof (struct sockaddr_in);
+ addr_len = sizeof (struct sockaddr_in6);
if (recvfrom(s, rec_buf, NS_PACKETSZ, 0,
(struct sockaddr *)&from_addr, &addr_len) == -1) {
- syslog(LOG_ERR, "dyndns: UDP recv error");
+ syslog(LOG_ERR, "dyndns: UDP recv error ");
return (-1);
}
break;
@@ -1441,7 +1548,6 @@
return (0);
}
-
/*
* dyndns_sec_add_remove_entry
* Perform secure dynamic DNS update after getting security context.
@@ -1484,7 +1590,7 @@
OM_uint32 min, maj;
gss_buffer_desc in_mic, out_mic;
gss_ctx_id_t gss_context;
- int dns_ip;
+ smb_inaddr_t dns_ip;
char *key_name;
int buf_sz;
int level = 0;
@@ -1492,18 +1598,21 @@
assert(dns_str);
assert(*dns_str);
- dns_ip = inet_addr(dns_str);
+ if (inet_pton(AF_INET, dns_str, &dns_ip) == 1)
+ dns_ip.a_family = AF_INET;
+ else if (inet_pton(AF_INET6, dns_str, &dns_ip) == 1)
+ dns_ip.a_family = AF_INET6;
sec_retry_higher:
if ((gss_context = dyndns_get_sec_context(hostname,
- dns_ip)) == NULL) {
+ &dns_ip)) == NULL) {
return (-1);
}
key_name = (char *)hostname;
- if ((s2 = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) {
+ if ((s2 = dyndns_open_init_socket(SOCK_DGRAM, &dns_ip, 53)) < 0) {
if (gss_context != GSS_C_NO_CONTEXT)
(void) gss_delete_sec_context(&min, &gss_context, NULL);
return (-1);
@@ -1598,40 +1707,71 @@
* 0 : an entry does not exist
*/
/*ARGSUSED*/
+
static int
dyndns_search_entry(int update_zone, const char *hostname, const char *ip_addr,
int update_type, struct timeval *time_out, int *is_match)
{
- struct hostent *hentry;
- struct in_addr in;
- in_addr_t ip;
- int i;
+ smb_inaddr_t ipaddr, dnsip;
+ char dns_hostname[NI_MAXHOST];
+ struct addrinfo hints, *res = NULL;
+ int salen;
+ int family;
*is_match = 0;
+ if (inet_pton(AF_INET, ip_addr, &ipaddr) == 1) {
+ salen = sizeof (ipaddr.a_ipv4);
+ family = AF_INET;
+ } else if (inet_pton(AF_INET6, ip_addr, &ipaddr) == 1) {
+ salen = sizeof (ipaddr.a_ipv6);
+ family = AF_INET6;
+ }
if (update_zone == UPDATE_FORW) {
- hentry = gethostbyname(hostname);
- if (hentry) {
- ip = inet_addr(ip_addr);
- for (i = 0; hentry->h_addr_list[i]; i++) {
- (void) memcpy(&in.s_addr,
- hentry->h_addr_list[i], sizeof (in.s_addr));
- if (ip == in.s_addr) {
- *is_match = 1;
- break;
+ bzero((char *)&hints, sizeof (hints));
+ hints.ai_family = family;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(hostname, NULL, &hints, &res)) {
+ return (NULL);
+ }
+ if (res) {
+ /*
+ * if both ips aren't the same family skip to
+ * the next record
+ */
+ do {
+ if ((res->ai_family == AF_INET) &&
+ (family == AF_INET)) {
+ (void) memcpy(&dnsip, &res->ai_addr[0],
+ salen);
+ if (ipaddr.a_ipv4 ==
+ dnsip.a_ipv4) {
+ *is_match = 1;
+ break;
+ }
+ } else if ((res->ai_family == AF_INET6) &&
+ (family == AF_INET6)) {
+ (void) memcpy(&dnsip, &res->ai_addr[0],
+ salen);
+ /* need compare macro here */
+ if (!memcmp(&ipaddr, &dnsip,
+ IN6ADDRSZ)) {
+ *is_match = 1;
+ break;
+ }
}
- }
+ } while (res->ai_next);
+ freeaddrinfo(res);
return (1);
}
} else {
- int dns_ip = inet_addr(ip_addr);
- hentry = gethostbyaddr((char *)&dns_ip, 4, AF_INET);
- if (hentry) {
- if (strncasecmp(hentry->h_name, hostname,
- strlen(hostname)) == 0) {
- *is_match = 1;
- }
- return (1);
+ if (dyndns_getnameinfo(&ipaddr, dns_hostname, NI_MAXHOST, 0)) {
+ return (NULL);
}
+ if (strncasecmp(dns_hostname, hostname,
+ strlen(hostname)) == 0) {
+ *is_match = 1;
+ }
+ return (1);
}
/* entry does not exist */
@@ -1679,17 +1819,16 @@
int s;
uint16_t id, rid;
char buf[NS_PACKETSZ], buf2[NS_PACKETSZ];
- int ret, dns_ip;
+ int ret;
int is_exist, is_match;
struct timeval timeout;
int buf_sz;
int level = 0;
+ smb_inaddr_t dns_ip;
assert(dns_str);
assert(*dns_str);
- dns_ip = inet_addr(dns_str);
-
if (do_check == DNS_CHECK && del_type != DEL_ALL) {
is_exist = dyndns_search_entry(update_zone, hostname, ip_addr,
update_type, &timeout, &is_match);
@@ -1701,10 +1840,14 @@
}
}
+ if (inet_pton(AF_INET, dns_str, &dns_ip) == 1)
+ dns_ip.a_family = AF_INET;
+ else if (inet_pton(AF_INET6, dns_str, &dns_ip) == 1)
+ dns_ip.a_family = AF_INET6;
+
retry_higher:
- if ((s = dyndns_open_init_socket(SOCK_DGRAM, dns_ip, 53)) < 0) {
+ if ((s = dyndns_open_init_socket(SOCK_DGRAM, &dns_ip, 53)) < 0)
return (-1);
- }
id = 0;
if ((buf_sz = dyndns_build_add_remove_msg(buf, update_zone, hostname,
@@ -1775,37 +1918,32 @@
dyndns_add_entry(int update_zone, const char *hostname, const char *ip_addr,
int life_time)
{
- char *dns_str;
+ const char *dns_str;
char *which_zone;
- struct in_addr ns_list[MAXNS];
+ smb_inaddr_t ns_list[MAXNS];
+ char dns_buf[INET6_ADDRSTRLEN];
int i, cnt;
- int addr, rc = 0;
+ int rc = 0;
- if (hostname == NULL || ip_addr == NULL)
+ if (hostname == NULL || ip_addr == NULL) {
return (-1);
-
- addr = (int)inet_addr(ip_addr);
- if ((addr == -1) || (addr == 0))
- return (-1);
-
- cnt = smb_get_nameservers(ns_list, MAXNS);
+ }
+ cnt = smb_get_nameservers(&ns_list[0], MAXNS);
for (i = 0; i < cnt; i++) {
- dns_str = inet_ntoa(ns_list[i]);
- if ((dns_str == NULL) ||
- (strcmp(dns_str, "0.0.0.0") == 0)) {
+ dns_str = smb_inet_ntop(&ns_list[i], dns_buf,
+ SMB_IPSTRLEN(ns_list[i].a_family));
+ if (dns_str == NULL)
continue;
- }
which_zone = (update_zone == UPDATE_FORW) ?
"forward" : "reverse";
-
syslog(LOG_DEBUG, "dyndns %s lookup zone update %s (%s)",
which_zone, hostname, ip_addr);
if (dyndns_add_remove_entry(update_zone, hostname,
ip_addr, life_time,
- UPDATE_ADD, DNS_NOCHECK, DEL_NONE, dns_str) != -1) {
+ UPDATE_ADD, DNS_NOCHECK, DEL_NONE, dns_buf) != -1) {
rc = 1;
break;
}
@@ -1835,46 +1973,44 @@
dyndns_remove_entry(int update_zone, const char *hostname, const char *ip_addr,
int del_type)
{
- char *dns_str;
- char *which_zone;
- struct in_addr ns_list[MAXNS];
+ const char *dns_str;
+ smb_inaddr_t ns_list[MAXNS];
+ char dns_buf[INET6_ADDRSTRLEN];
int i, cnt, scnt;
- int addr;
if ((hostname == NULL || ip_addr == NULL)) {
return (-1);
}
-
- addr = (int)inet_addr(ip_addr);
- if ((addr == -1) || (addr == 0)) {
- return (-1);
- }
-
cnt = smb_get_nameservers(ns_list, MAXNS);
scnt = 0;
-
for (i = 0; i < cnt; i++) {
- dns_str = inet_ntoa(ns_list[i]);
- if ((dns_str == NULL) ||
- (strcmp(dns_str, "0.0.0.0") == 0)) {
+ dns_str = smb_inet_ntop(&ns_list[i], dns_buf,
+ SMB_IPSTRLEN(ns_list[i].a_family));
+ if (dns_str == NULL)
continue;
+ if (update_zone == UPDATE_FORW) {
+ if (del_type == DEL_ONE) {
+ syslog(LOG_DEBUG, "Dynamic update "
+ "on forward lookup "
+ "zone for %s (%s)...\n", hostname, ip_addr);
+ } else {
+ syslog(LOG_DEBUG, "Removing all "
+ "entries of %s "
+ "in forward lookup zone...\n", hostname);
+ }
+ } else {
+ if (del_type == DEL_ONE) {
+ syslog(LOG_DEBUG, "Dynamic update "
+ "on reverse lookup "
+ "zone for %s (%s)...\n", hostname, ip_addr);
+ } else {
+ syslog(LOG_DEBUG, "Removing all "
+ "entries of %s "
+ "in reverse lookup zone...\n", ip_addr);
+ }
}
-
- which_zone = (update_zone == UPDATE_FORW) ?
- "forward" : "reverse";
-
- if (del_type == DEL_ONE) {
- syslog(LOG_DEBUG,
- "dyndns %s lookup zone remove %s (%s)",
- which_zone, hostname, ip_addr);
- } else {
- syslog(LOG_DEBUG,
- "dyndns %s lookup zone remove all %s",
- which_zone, hostname);
- }
-
if (dyndns_add_remove_entry(update_zone, hostname, ip_addr, 0,
- UPDATE_DEL, DNS_NOCHECK, del_type, dns_str) != -1) {
+ UPDATE_DEL, DNS_NOCHECK, del_type, dns_buf) != -1) {
scnt++;
break;
}
@@ -1900,12 +2036,12 @@
* -1: some dynamic DNS updates errors
* 0: successful or DDNS disabled.
*/
-static int
+int
dyndns_update_core(char *fqdn)
{
int forw_update_ok, error;
- char *my_ip;
- struct in_addr addr;
+ char my_ip[INET6_ADDRSTRLEN];
+ const char *my_str;
smb_niciter_t ni;
int rc;
char fqhn[MAXHOSTNAMELEN];
@@ -1938,32 +2074,31 @@
do {
if (ni.ni_nic.nic_sysflags & IFF_PRIVATE)
continue;
-
- addr.s_addr = ni.ni_nic.nic_ip;
- my_ip = (char *)strdup(inet_ntoa(addr));
- if (my_ip == NULL) {
+ /* first try ipv4, then ipv6 */
+ my_str = smb_inet_ntop(&ni.ni_nic.nic_ip, my_ip,
+ SMB_IPSTRLEN(ni.ni_nic.nic_ip.a_family));
+ if (my_str == NULL) {
error++;
continue;
}
if (forw_update_ok) {
- rc = dyndns_add_entry(UPDATE_FORW, fqhn, my_ip,
+ rc = dyndns_add_entry(UPDATE_FORW, fqhn, my_str,
DDNS_TTL);
if (rc == -1)
error++;
}
- rc = dyndns_remove_entry(UPDATE_REV, fqhn, my_ip, DEL_ALL);
+ rc = dyndns_remove_entry(UPDATE_REV, fqhn, my_str, DEL_ALL);
if (rc == 0) {
- rc = dyndns_add_entry(UPDATE_REV, fqhn, my_ip,
+ rc = dyndns_add_entry(UPDATE_REV, fqhn, my_str,
DDNS_TTL);
}
if (rc == -1)
error++;
- (void) free(my_ip);
} while (smb_nic_getnext(&ni) == 0);
return ((error == 0) ? 0 : -1);
@@ -1980,15 +2115,15 @@
* -1: some dynamic DNS updates errors
* 0: successful or DDNS disabled.
*/
-static int
+int
dyndns_clear_rev_zone(char *fqdn)
{
int error;
- char *my_ip;
- struct in_addr addr;
+ char my_ip[INET6_ADDRSTRLEN];
smb_niciter_t ni;
int rc;
char fqhn[MAXHOSTNAMELEN];
+ const char *my_str;
if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE))
return (0);
@@ -2005,10 +2140,9 @@
do {
if (ni.ni_nic.nic_sysflags & IFF_PRIVATE)
continue;
-
- addr.s_addr = ni.ni_nic.nic_ip;
- my_ip = (char *)strdup(inet_ntoa(addr));
- if (my_ip == NULL) {
+ my_str = smb_inet_ntop(&ni.ni_nic.nic_ip, my_ip,
+ SMB_IPSTRLEN(ni.ni_nic.nic_ip.a_family));
+ if (my_str == NULL) {
error++;
continue;
}
@@ -2017,7 +2151,6 @@
if (rc != 0)
error++;
- (void) free(my_ip);
} while (smb_nic_getnext(&ni) == 0);
return ((error == 0) ? 0 : -1);
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_datagram.c Sun Feb 01 19:44:54 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"
-
/*
* Description:
*
@@ -316,7 +314,7 @@
smb_netbios_datagram_send(struct name_entry *src, struct name_entry *dest,
unsigned char *data, int length)
{
- uint32_t ipaddr;
+ smb_inaddr_t ipaddr;
size_t count, srclen, destlen, sinlen;
struct addr_entry *addr;
struct sockaddr_in sin;
@@ -375,12 +373,13 @@
sinlen = sizeof (sin);
addr = &dest->addr_list;
do {
- ipaddr = addr->sin.sin_addr.s_addr;
+ ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
+ ipaddr.a_family = AF_INET;
/* Don't send anything to myself... */
- if (smb_nic_exists(ipaddr, B_FALSE))
+ if (smb_nic_exists(&ipaddr, B_FALSE))
goto next;
- sin.sin_addr.s_addr = ipaddr;
+ sin.sin_addr.s_addr = ipaddr.a_ipv4;
sin.sin_port = addr->sin.sin_port;
(void) sendto(datagram_sock, buffer, count, 0,
(struct sockaddr *)&sin, sinlen);
@@ -396,7 +395,7 @@
smb_netbios_datagram_send_to_net(struct name_entry *src,
struct name_entry *dest, char *data, int length)
{
- uint32_t ipaddr;
+ smb_inaddr_t ipaddr;
size_t count, srclen, destlen, sinlen;
struct addr_entry *addr;
struct sockaddr_in sin;
@@ -455,11 +454,12 @@
sinlen = sizeof (sin);
addr = &dest->addr_list;
do {
- ipaddr = addr->sin.sin_addr.s_addr;
- if (smb_nic_exists(ipaddr, B_FALSE))
+ ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
+ ipaddr.a_family = AF_INET;
+ if (smb_nic_exists(&ipaddr, B_FALSE))
goto next;
- sin.sin_addr.s_addr = ipaddr;
+ sin.sin_addr.s_addr = ipaddr.a_ipv4;
sin.sin_port = addr->sin.sin_port;
(void) sendto(datagram_sock, buffer, count, 0,
(struct sockaddr *)&sin, sinlen);
@@ -951,6 +951,7 @@
struct sockaddr_in sin;
struct datagram *datagram;
int bytes, flag = 1;
+ smb_inaddr_t ipaddr;
(void) mutex_lock(&smb_dgq_mtx);
bzero(&smb_datagram_queue, sizeof (smb_datagram_queue));
@@ -1005,8 +1006,9 @@
}
/* Ignore any incoming packets from myself... */
- if (smb_nic_exists(datagram->inaddr.sin.sin_addr.s_addr,
- B_FALSE)) {
+ ipaddr.a_ipv4 = datagram->inaddr.sin.sin_addr.s_addr;
+ ipaddr.a_family = AF_INET;
+ if (smb_nic_exists(&ipaddr, B_FALSE)) {
goto ignore;
}
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c Sun Feb 01 19:44:54 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.
*/
@@ -2134,6 +2134,7 @@
unsigned char *scan_end;
unsigned char data[MAX_NETBIOS_REPLY_DATA_SIZE];
boolean_t scan_done = B_FALSE;
+ smb_inaddr_t ipaddr;
bzero(&packet, sizeof (struct name_packet));
bzero(&answer, sizeof (struct resource_record));
@@ -2160,7 +2161,9 @@
scan_end = data + MAX_NETBIOS_REPLY_DATA_SIZE;
- if (smb_nic_exists(addr->sin.sin_addr.s_addr, B_TRUE))
+ ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
+ ipaddr.a_family = AF_INET;
+ if (smb_nic_exists(&ipaddr, B_TRUE))
net_ipaddr = addr->sin.sin_addr.s_addr;
else
net_ipaddr = 0;
@@ -4584,12 +4587,14 @@
continue;
smb_init_name_struct((unsigned char *)ni.ni_nic.nic_host,
- 0x00, 0, ni.ni_nic.nic_ip, htons(DGM_SRVC_UDP_PORT),
+ 0x00, 0, ni.ni_nic.nic_ip.a_ipv4,
+ htons(DGM_SRVC_UDP_PORT),
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, htons(DGM_SRVC_UDP_PORT),
+ 0x20, 0, ni.ni_nic.nic_ip.a_ipv4,
+ htons(DGM_SRVC_UDP_PORT),
NAME_ATTR_UNIQUE, NAME_ATTR_LOCAL, &name);
(void) smb_netbios_cache_insert(&name);
} while (smb_nic_getnext(&ni) == 0);
@@ -4643,6 +4648,7 @@
int flag = 1;
char *buf;
worker_param_t *worker_param;
+ smb_inaddr_t ipaddr;
/*
* Initialize reply_queue
@@ -4719,7 +4725,10 @@
}
/* Ignore any incoming packets from myself... */
- if (smb_nic_exists(addr->sin.sin_addr.s_addr, B_FALSE))
+
+ ipaddr.a_ipv4 = addr->sin.sin_addr.s_addr;
+ ipaddr.a_family = AF_INET;
+ if (smb_nic_exists(&ipaddr, B_FALSE))
goto ignore;
/*
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c Sun Feb 01 19:44:54 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.
*/
@@ -480,15 +480,14 @@
{
static int initialized = 0;
uint32_t ipaddr;
- uint32_t prefer_ipaddr = 0;
- char ipstr[16];
- char srcip[16];
+ uint32_t prefer_ipaddr;
+ char ipstr[INET_ADDRSTRLEN];
+ char srcip[INET_ADDRSTRLEN];
int rc;
- (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr),
- srcip, sizeof (srcip));
+ (void) inet_ntop(AF_INET, &src_ipaddr, srcip, INET_ADDRSTRLEN);
- rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, sizeof (ipstr));
+ rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, INET_ADDRSTRLEN);
if (rc == SMBD_SMF_OK) {
rc = inet_pton(AF_INET, ipstr, &prefer_ipaddr);
if (rc == 0)
@@ -505,8 +504,8 @@
ntdomain_info.n_domain, src_name, srcip);
if (ntdomain_info.n_ipaddr != 0) {
- if (prefer_ipaddr != 0 && prefer_ipaddr ==
- ntdomain_info.n_ipaddr) {
+ if (prefer_ipaddr != 0 &&
+ prefer_ipaddr == ntdomain_info.n_ipaddr) {
syslog(LOG_DEBUG, "DC for %s: %s [%s]",
ntdomain_info.n_domain, src_name, srcip);
(void) mutex_unlock(&ntdomain_mtx);
@@ -533,17 +532,24 @@
static int
smb_better_dc(uint32_t cur_ip, uint32_t new_ip)
{
+ smb_inaddr_t ipaddr;
+
/*
* If we don't have any current DC,
* then use the new one of course.
*/
+
if (cur_ip == 0)
return (1);
- if (smb_nic_exists(cur_ip, B_TRUE))
+ ipaddr.a_family = AF_INET;
+ ipaddr.a_ipv4 = cur_ip;
+ if (smb_nic_exists(&ipaddr, B_TRUE))
return (0);
- if (smb_nic_exists(new_ip, B_TRUE))
+ ipaddr.a_family = AF_INET;
+ ipaddr.a_ipv4 = new_ip;
+ if (smb_nic_exists(&ipaddr, B_TRUE))
return (1);
/*
* Otherwise, just keep the old one.
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h Sun Feb 01 19:44:54 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.
*/
@@ -110,7 +110,7 @@
struct sdb_session {
char srv_name[MAXHOSTNAMELEN];
- uint32_t srv_ipaddr;
+ smb_inaddr_t srv_ipaddr;
char domain[MAXHOSTNAMELEN];
char scope[SMB_PI_MAX_SCOPE];
char native_os[SMB_PI_MAX_NATIVE_OS];
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c Sun Feb 01 19:44:54 2009 -0700
@@ -19,14 +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.
*/
-/*
- * SMB session logon and logoff functions. See CIFS section 4.1.
- */
-
#include <pthread.h>
#include <string.h>
#include <strings.h>
@@ -39,12 +35,13 @@
#include <arpa/inet.h>
#include <smbsrv/wintypes.h>
#include <smbsrv/libsmbrdr.h>
-#include <smbsrv/libmlsvc.h>
#include <smbsrv/ntstatus.h>
#include <smbsrv/smb.h>
#include <smbrdr_ipc_util.h>
#include <smbrdr.h>
+#define SMBRDR_ANON_USER "IPC$"
+
static int smbrdr_anonymous_logon(char *domain_controller, char *domain_name);
static int smbrdr_auth_logon(char *domain_controller, char *domain_name,
char *username);
@@ -58,16 +55,16 @@
/*
* mlsvc_logon
*
- * If the username is MLSVC_ANON_USER, an anonymous session will be established.
- * Otherwise, an authenticated session will be established based on the
- * specified credentials.
+ * 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)
{
int rc;
- if (strcmp(username, MLSVC_ANON_USER) == 0)
+ if (strcmp(username, SMBRDR_ANON_USER) == 0)
rc = smbrdr_anonymous_logon(domain_controller, domain);
else
rc = smbrdr_auth_logon(domain_controller, domain, username);
@@ -85,7 +82,7 @@
static int
smbrdr_anonymous_logon(char *domain_controller, char *domain_name)
{
- if (smbrdr_logon_validate(domain_controller, MLSVC_ANON_USER))
+ if (smbrdr_logon_validate(domain_controller, SMBRDR_ANON_USER))
return (0);
if (smbrdr_negotiate(domain_controller, domain_name) != 0) {
@@ -93,7 +90,7 @@
return (-1);
}
- if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0) < 0) {
+ if (smbrdr_logon_user(domain_controller, SMBRDR_ANON_USER, 0) < 0) {
syslog(LOG_DEBUG, "smbrdr_anonymous_logon: logon failed");
return (-1);
}
@@ -207,7 +204,7 @@
int ret;
if ((server == NULL) || (username == NULL) ||
- ((strcmp(username, MLSVC_ANON_USER) != 0) && (pwd == NULL)))
+ ((strcmp(username, SMBRDR_ANON_USER) != 0) && (pwd == NULL)))
return (-1);
session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE);
--- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c Sun Feb 01 19:44:54 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.
*/
@@ -46,10 +46,10 @@
#include <smbsrv/netbios.h>
#include <smbsrv/cifs.h>
#include <smbsrv/ntstatus.h>
-#include <smbsrv/libmlsvc.h>
#include <smbrdr.h>
#include <smbrdr_ipc_util.h>
+#define SMBRDR_DOMAIN_MAX 32
static uint16_t smbrdr_ports[] = {
SMB_SRVC_TCP_PORT,
@@ -58,7 +58,7 @@
static int smbrdr_nports = sizeof (smbrdr_ports) / sizeof (smbrdr_ports[0]);
-static struct sdb_session session_table[MLSVC_DOMAIN_MAX];
+static struct sdb_session session_table[SMBRDR_DOMAIN_MAX];
static mutex_t smbrdr_screate_mtx;
static uint32_t session_id = 0;
@@ -229,22 +229,35 @@
{
char hostname[MAXHOSTNAMELEN];
struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
int sock, rc;
mts_wchar_t unicode_server_name[SMB_PI_MAX_DOMAIN];
char server_name[SMB_PI_MAX_DOMAIN];
unsigned int cpid = oem_get_smb_cpid();
+ char ipstr[INET6_ADDRSTRLEN];
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) {
+ if ((sock = socket(sess->srv_ipaddr.a_family, SOCK_STREAM, 0)) <= 0) {
syslog(LOG_DEBUG, "smbrdr: socket failed: %s", strerror(errno));
return (-1);
}
+ if (sess->srv_ipaddr.a_family == AF_INET) {
+ bzero(&sin, sizeof (struct sockaddr_in));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = sess->srv_ipaddr.a_ipv4;
+ sin.sin_port = htons(port);
+ rc = connect(sock, (struct sockaddr *)&sin, sizeof (sin));
+ } else {
+ (void) smb_inet_ntop(&sess->srv_ipaddr, ipstr,
+ SMB_IPSTRLEN(sess->srv_ipaddr.a_family));
+ bzero(&sin6, sizeof (struct sockaddr_in6));
+ sin6.sin6_family = AF_INET6;
+ bcopy(&sess->srv_ipaddr.a_ipv6, &sin6.sin6_addr.s6_addr,
+ IPV6_ADDR_LEN);
+ sin6.sin6_port = htons(port);
+ rc = connect(sock, (struct sockaddr *)&sin6, sizeof (sin6));
+ }
- bzero(&sin, sizeof (struct sockaddr_in));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = sess->srv_ipaddr;
- sin.sin_port = htons(port);
-
- if ((rc = connect(sock, (struct sockaddr *)&sin, sizeof (sin))) < 0) {
+ if (rc < 0) {
syslog(LOG_DEBUG, "smbrdr: connect failed: %s",
strerror(errno));
if (sock != 0)
@@ -391,7 +404,7 @@
smbrdr_session_init(char *domain_controller, char *domain)
{
struct sdb_session *session = NULL;
- uint32_t ipaddr;
+ smb_inaddr_t ipaddr;
int i, rc;
struct hostent *h;
@@ -405,9 +418,10 @@
}
(void) memcpy(&ipaddr, h->h_addr, h->h_length);
+ ipaddr.a_family = h->h_addrtype;
freehostent(h);
- for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) {
+ for (i = 0; i < SMBRDR_DOMAIN_MAX; ++i) {
session = &session_table[i];
(void) rw_wrlock(&session->rwl);
@@ -526,7 +540,7 @@
if (server == NULL)
return (NULL);
- for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) {
+ for (i = 0; i < SMBRDR_DOMAIN_MAX; ++i) {
session = &session_table[i];
(lmode == SDB_SLCK_READ) ? (void) rw_rdlock(&session->rwl) :
@@ -594,18 +608,16 @@
{
struct sdb_session *session;
struct sdb_logon *logon;
- char ipstr[16];
+ char ipstr[INET6_ADDRSTRLEN];
int i;
- for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) {
+ for (i = 0; i < SMBRDR_DOMAIN_MAX; ++i) {
session = &session_table[i];
(void) rw_rdlock(&session->rwl);
if (session->state != SDB_SSTATE_START) {
- (void) inet_ntop(AF_INET,
- (const void *)(&session->srv_ipaddr),
- ipstr, sizeof (ipstr));
-
+ (void) smb_inet_ntop(&session->srv_ipaddr, ipstr,
+ SMB_IPSTRLEN(session->srv_ipaddr.a_family));
syslog(LOG_DEBUG, "session[%d]: state=%d",
i, session->state);
syslog(LOG_DEBUG, "session[%d]: %s %s (%s)", i,
--- a/usr/src/pkgdefs/etc/exception_list_i386 Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_i386 Sun Feb 01 19:44:54 2009 -0700
@@ -1026,6 +1026,7 @@
usr/include/smbsrv/smb_i18n.h i386
usr/include/smbsrv/smb_idmap.h i386
usr/include/smbsrv/smb_incl.h i386
+usr/include/smbsrv/smb_inet.h i386
usr/include/smbsrv/smb_ioctl.h i386
usr/include/smbsrv/smb_kproto.h i386
usr/include/smbsrv/smb_kstat.h i386
@@ -1038,7 +1039,6 @@
usr/include/smbsrv/smb_xdr.h i386
usr/include/smbsrv/smbfmt.h i386
usr/include/smbsrv/smbinfo.h i386
-usr/include/smbsrv/smbtrans.h i386
usr/include/smbsrv/string.h i386
usr/include/smbsrv/svrapi.h i386
usr/include/smbsrv/winioctl.h i386
--- a/usr/src/pkgdefs/etc/exception_list_sparc Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/pkgdefs/etc/exception_list_sparc Sun Feb 01 19:44:54 2009 -0700
@@ -1124,6 +1124,7 @@
usr/include/smbsrv/smb_i18n.h sparc
usr/include/smbsrv/smb_idmap.h sparc
usr/include/smbsrv/smb_incl.h sparc
+usr/include/smbsrv/smb_inet.h sparc
usr/include/smbsrv/smb_ioctl.h sparc
usr/include/smbsrv/smb_kproto.h sparc
usr/include/smbsrv/smb_kstat.h sparc
@@ -1136,7 +1137,6 @@
usr/include/smbsrv/smb_xdr.h sparc
usr/include/smbsrv/smbfmt.h sparc
usr/include/smbsrv/smbinfo.h sparc
-usr/include/smbsrv/smbtrans.h sparc
usr/include/smbsrv/string.h sparc
usr/include/smbsrv/svrapi.h sparc
usr/include/smbsrv/winioctl.h sparc
--- a/usr/src/uts/common/Makefile.files Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/Makefile.files Sun Feb 01 19:44:54 2009 -0700
@@ -1033,6 +1033,7 @@
nfs4_deleg_ops.o nfs4_srv_readdir.o nfs4_dispatch.o
SMBSRV_SHARED_OBJS += \
+ smb_inet.o \
smb_match.o \
smb_msgbuf.o \
smb_oem.o \
@@ -1056,7 +1057,6 @@
smb_check_directory.o \
smb_close.o \
smb_common_open.o \
- smb_common_search.o \
smb_common_transact.o \
smb_create.o \
smb_create_directory.o \
@@ -1066,7 +1066,6 @@
smb_echo.o \
smb_fem.o \
smb_find.o \
- smb_find_unique.o \
smb_flush.o \
smb_fsops.o \
smb_init.o \
@@ -1106,7 +1105,6 @@
smb_read.o \
smb_rename.o \
smb_sd.o \
- smb_search.o \
smb_seek.o \
smb_server.o \
smb_session.o \
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c Sun Feb 01 19:44:54 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.
*/
@@ -548,7 +548,8 @@
if ((!(op->desired_access &
(FILE_WRITE_DATA | FILE_APPEND_DATA |
FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA))) ||
- (!smb_sattr_check(&node->attr, NULL, op->dattr))) {
+ (!smb_sattr_check(node->attr.sa_dosattr,
+ op->dattr, NULL))) {
rw_exit(&node->n_share_lock);
smb_node_release(node);
smb_node_release(dnode);
--- a/usr/src/uts/common/fs/smbsrv/smb_common_search.c Sun Feb 01 15:33:03 2009 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +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.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Implementation of smb_rdir_open, smb_rdir_next and smb_rdir_close.
- */
-
-#include <smbsrv/smb_incl.h>
-#include <smbsrv/smb_fsops.h>
-
-/*
- * smb_rdir_open
- */
-int
-smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr)
-{
- smb_odir_t *od;
- smb_node_t *node;
- char *last_component;
- int rc;
-
- last_component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
-
- if ((rc = smb_pathname_reduce(sr, sr->user_cr, path,
- sr->tid_tree->t_snode, sr->tid_tree->t_snode,
- &node, last_component)) != 0) {
- kmem_free(last_component, MAXNAMELEN);
- smbsr_errno(sr, rc);
- return (-1);
- }
-
- if ((node->vp)->v_type != VDIR) {
- smb_node_release(node);
- kmem_free(last_component, MAXNAMELEN);
- smbsr_error(sr, 0, ERRDOS, ERRbadpath);
- return (-1);
- }
-
- rc = smb_fsop_access(sr, sr->user_cr, node, FILE_LIST_DIRECTORY);
- if (rc != 0) {
- smb_node_release(node);
- kmem_free(last_component, MAXNAMELEN);
-
- if (sr->smb_com == SMB_COM_SEARCH) {
- smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
- ERRDOS, ERROR_NO_MORE_FILES);
- return (-2);
- } else {
- smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
- ERRDOS, ERROR_ACCESS_DENIED);
- return (-1);
- }
- }
-
- od = smb_odir_open(sr->tid_tree, node, last_component, sr->smb_pid,
- sattr);
- kmem_free(last_component, sizeof (od->d_pattern));
- if (od == NULL) {
- smb_node_release(node);
- smbsr_error(sr, 0, ERRDOS, ERROR_NO_MORE_FILES);
- return (-1);
- }
-
- sr->smb_sid = od->d_sid;
- sr->sid_odir = od;
- return (0);
-}
-
-
-/*
- * smb_rdir_next
- *
- * Returns:
- * 0 Found an entry
- * ENOENT There is no (more) entry
- * error code An error happened
- */
-int
-smb_rdir_next(
- smb_request_t *sr,
- smb_node_t **rnode,
- smb_odir_context_t *pc)
-{
- struct smb_odir *dir;
- ino64_t fileid;
- int rc, n_name;
- char last_component[MAXNAMELEN];
- char namebuf[MAXNAMELEN];
- smb_node_t *tmp_snode;
- smb_node_t *dnode;
- smb_node_t *fnode;
- smb_attr_t ret_attr;
-
- ASSERT(sr->sid_odir);
- dir = sr->sid_odir;
-
- if (dir->d_state == SMB_ODIR_STATE_CLOSED) {
- return (ENOENT);
- }
-
- if (dir->d_wildcards == 0) {
- /* There are no wildcards in pattern */
- if (pc->dc_cookie != 0) {
- /* Already found entry... */
- return (ENOENT);
- }
-
- pc->dc_name[0] = '\0';
- pc->dc_shortname[0] = '\0';
- pc->dc_name83[0] = '\0';
-
- rc = smb_fsop_lookup(sr, sr->user_cr, 0,
- sr->tid_tree->t_snode, dir->d_dir_snode, dir->d_pattern,
- &fnode, &pc->dc_attr, pc->dc_shortname, pc->dc_name83);
-
- if (rc != 0)
- return (rc);
-
- /*
- * We are here if there was a successful lookup of the
- * name. The name may be a mangled name. If it was,
- * then shortname has the copy of it. So, we may
- * not need to do mangling later.
- *
- * dir->name will contain the case-preserved name.
- * If that name is not available (this should not
- * happen), then copy dir->pattern into dir->name.
- */
-
- if (fnode->od_name) {
- (void) strcpy(pc->dc_name, fnode->od_name);
- } else {
- (void) strcpy(pc->dc_name, dir->d_pattern);
- }
-
- /* Root of file system? */
- if ((strcmp(dir->d_pattern, "..") == 0) &&
- (dir->d_dir_snode == sr->tid_tree->t_snode)) {
- smb_node_release(fnode);
- smb_node_ref(sr->tid_tree->t_snode);
- fnode = sr->tid_tree->t_snode;
- } else if (pc->dc_attr.sa_vattr.va_type == VLNK) {
- (void) strcpy(namebuf, dir->d_pattern);
-
- tmp_snode = fnode;
- rc = smb_pathname_reduce(sr, sr->user_cr, namebuf,
- sr->tid_tree->t_snode, dir->d_dir_snode,
- &dnode, last_component);
-
- if (rc != 0) {
- fnode = tmp_snode;
- } else {
- rc = smb_fsop_lookup(sr, sr->user_cr,
- SMB_FOLLOW_LINKS, sr->tid_tree->t_snode,
- dnode, last_component, &fnode, &ret_attr,
- 0, 0);
-
- smb_node_release(dnode);
- if (rc != 0) {
- fnode = tmp_snode;
- } else {
- pc->dc_attr = ret_attr;
- smb_node_release(tmp_snode);
- }
- }
- }
-
- pc->dc_dattr = smb_node_get_dosattr(fnode);
-
- /* Obey search attributes */
- if (!smb_sattr_check(&fnode->attr, pc->dc_name, dir->d_sattr)) {
- smb_node_release(fnode);
- return (ENOENT);
- }
-
- /*
- * If name not already mangled, do it.
- *
- * The name will only be mangled if smb_needs_mangle()
- * determines that it is required. Mangling due to
- * case-insensitive collisions is not necessary here.
- */
- if (pc->dc_name83[0] == '\0')
- (void) smb_mangle_name(fnode->attr.sa_vattr.va_nodeid,
- pc->dc_name, pc->dc_shortname, pc->dc_name83, 0);
- if (rnode)
- *rnode = fnode;
- else
- smb_node_release(fnode);
-
- pc->dc_cookie = (uint32_t)-1;
- return (0);
- }
-
- /* There are wildcards in pattern */
- for (;;) {
- if (dir->d_state == SMB_ODIR_STATE_CLOSED) {
- return (ENOENT);
- }
-
- /* sizeof dir->name == 256 */
- n_name = (sizeof (pc->dc_name)) - 1;
-
- rc = smb_fsop_readdir(sr, sr->user_cr, dir->d_dir_snode,
- &pc->dc_cookie, pc->dc_name, &n_name, &fileid, NULL,
- NULL, NULL);
- if (rc != 0) {
- return (rc);
- }
-
- if (n_name == 0) /* EOF */
- break;
- pc->dc_name[n_name] = '\0';
-
- /*
- * Don't return "." or ".." unless FILE_ATTRIBUTE_HIDDEN
- * is set. We have to code this by hand because these are
- * virtual directory entries and they are not hidden.
- */
- if (((dir->d_sattr & FILE_ATTRIBUTE_HIDDEN) == 0) &&
- smb_is_dot_or_dotdot(pc->dc_name)) {
- continue;
- }
-
- /* may match a mangled name or "real" name */
- if (smb_component_match(sr, fileid, dir, pc) <= 0)
- continue;
-
- /* Look up the "real" name */
- rc = smb_fsop_lookup(sr, sr->user_cr, 0, sr->tid_tree->t_snode,
- dir->d_dir_snode, pc->dc_name, &fnode, &pc->dc_attr, 0, 0);
-
- if (rc != 0) {
- if (rc != ENOENT)
- return (rc);
-
- continue;
- }
-
- /* Root of file system? */
- if ((strcmp(pc->dc_name, "..") == 0) &&
- (dir->d_dir_snode == sr->tid_tree->t_snode)) {
- smb_node_release(fnode);
- smb_node_ref(sr->tid_tree->t_snode);
- fnode = sr->tid_tree->t_snode;
- } else if (pc->dc_attr.sa_vattr.va_type == VLNK) {
- (void) strcpy(namebuf, pc->dc_name);
-
- smb_node_release(fnode);
- rc = smb_pathname_reduce(sr, sr->user_cr, namebuf,
- sr->tid_tree->t_snode, dir->d_dir_snode, &dnode,
- last_component);
-
- if (rc != 0) {
- continue;
- }
-
- rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
- sr->tid_tree->t_snode, dnode, last_component,
- &fnode, &ret_attr, 0, 0);
-
- smb_node_release(dnode);
- if (rc != 0) {
- continue;
- }
- pc->dc_attr = ret_attr;
- }
-
- pc->dc_dattr = smb_node_get_dosattr(fnode);
-
- /* Obey search attributes */
- if (!smb_sattr_check(&fnode->attr, NULL, dir->d_sattr)) {
- smb_node_release(fnode);
- continue;
- }
-
- if (rnode)
- *rnode = fnode;
- else
- smb_node_release(fnode);
-
- return (0);
- }
-
- return (ENOENT);
-}
-
-/*
- * smb_rdir_close
- */
-void
-smb_rdir_close(struct smb_request *sr)
-{
- smb_odir_t *od = sr->sid_odir;
-
- ASSERT(od);
- ASSERT(od->d_magic == SMB_ODIR_MAGIC);
-
- smb_odir_close(od);
- smb_odir_release(od);
- sr->sid_odir = NULL;
-}
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c Sun Feb 01 19:44:54 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.
*/
@@ -31,7 +31,7 @@
static int smb_delete_check_path(smb_request_t *, boolean_t *);
static int smb_delete_single_file(smb_request_t *, smb_error_t *);
static int smb_delete_multiple_files(smb_request_t *, smb_error_t *);
-static int smb_delete_find_fname(smb_request_t *, uint32_t *);
+static int smb_delete_find_fname(smb_request_t *, smb_odir_t *);
static int smb_delete_check_attr(smb_request_t *, smb_error_t *);
static int smb_delete_remove_file(smb_request_t *, smb_error_t *);
@@ -254,7 +254,7 @@
/*
* smb_delete_multiple_files
*
- * For each matching file found by smb_delete_find_name:
+ * For each matching file found by smb_delete_find_fname:
* 1. lookup file
* 2. check the file's attributes
* - The search ends with an error if a readonly file
@@ -273,14 +273,24 @@
smb_delete_multiple_files(smb_request_t *sr, smb_error_t *err)
{
int rc, deleted = 0;
- uint32_t cookie = 0;
smb_fqi_t *fqi;
smb_attr_t ret_attr;
+ uint16_t odid;
+ smb_odir_t *od;
fqi = &sr->arg.dirop.fqi;
+ /*
+ * Specify all search attributes (SMB_SEARCH_ATTRIBUTES) so that
+ * delete-specific checking can be done (smb_delete_check_attr).
+ */
+ if ((odid = smb_odir_open(sr, fqi->path, SMB_SEARCH_ATTRIBUTES)) == 0)
+ return (-1);
+ if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)
+ return (-1);
+
for (;;) {
- rc = smb_delete_find_fname(sr, &cookie);
+ rc = smb_delete_find_fname(sr, od);
if (rc != 0)
break;
@@ -293,6 +303,8 @@
if (smb_delete_check_attr(sr, err) != 0) {
smb_node_release(fqi->last_snode);
if (err->status == NT_STATUS_CANNOT_DELETE) {
+ smb_odir_release(od);
+ smb_odir_close(od);
return (-1);
}
if ((err->status == NT_STATUS_FILE_IS_A_DIRECTORY) &&
@@ -311,10 +323,14 @@
continue;
}
+ smb_odir_release(od);
+ smb_odir_close(od);
smb_node_release(fqi->last_snode);
return (-1);
}
+ smb_odir_release(od);
+ smb_odir_close(od);
if ((rc != 0) && (rc != ENOENT)) {
smbsr_map_errno(rc, err);
@@ -336,42 +352,52 @@
* Find next filename that matches search pattern (fqi->last_comp)
* and save it in fqi->last_comp_od.
*
+ * Case insensitivity note:
+ * If the tree is case insensitive and there's a case conflict
+ * with the name returned from smb_odir_read, smb_delete_find_fname
+ * performs case conflict name mangling to produce a unique filename.
+ * This ensures that any subsequent smb_fsop_lookup, (which will
+ * find the first case insensitive match) will find the correct file.
+ *
* Returns: 0 - success
* errno
*/
static int
-smb_delete_find_fname(smb_request_t *sr, uint32_t *cookie)
+smb_delete_find_fname(smb_request_t *sr, smb_odir_t *od)
{
- int rc, n_name;
- ino64_t fileid;
- smb_fqi_t *fqi;
- char name83[SMB_SHORTNAMELEN];
- char shortname[SMB_SHORTNAMELEN];
- boolean_t ignore_case;
+ int rc;
+ smb_odirent_t *odirent;
+ boolean_t eos;
+ char *name;
+ char shortname[SMB_SHORTNAMELEN];
+ char name83[SMB_SHORTNAMELEN];
+ smb_fqi_t *fqi;
fqi = &sr->arg.dirop.fqi;
-
- ignore_case = SMB_TREE_IS_CASEINSENSITIVE(sr);
+ odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
- for (;;) {
- n_name = sizeof (fqi->last_comp_od) - 1;
-
- rc = smb_fsop_readdir(sr, sr->user_cr, fqi->dir_snode, cookie,
- fqi->last_comp_od, &n_name, &fileid, NULL, NULL, NULL);
+ rc = smb_odir_read(sr, od, odirent, &eos);
+ if (rc != 0) {
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ return (rc);
+ }
+ if (eos) {
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ return (ENOENT);
+ }
- if (rc != 0)
- return (rc);
-
- /* check for EOF */
- if (n_name == 0)
- return (ENOENT);
+ /* if case conflict, force mangle and use shortname */
+ if ((od->d_ignore_case) && (odirent->od_eflags & ED_CASE_CONFLICT)) {
+ (void) smb_mangle_name(odirent->od_ino, odirent->od_name,
+ shortname, name83, 1);
+ name = shortname;
+ } else {
+ name = odirent->od_name;
+ }
+ (void) strlcpy(fqi->last_comp_od, name, sizeof (fqi->last_comp_od));
- fqi->last_comp_od[n_name] = '\0';
-
- if (smb_match_name(fileid, fqi->last_comp_od, shortname, name83,
- fqi->last_comp, ignore_case))
- return (0);
- }
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ return (0);
}
/*
--- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c Sun Feb 01 19:44:54 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.
*
*
@@ -548,9 +548,6 @@
if (sr->fid_ofile)
smbsr_disconnect_file(sr);
- if (sr->sid_odir)
- smbsr_disconnect_dir(sr);
-
if (sr->r_xa) {
if (sr->r_xa->xa_flags & SMB_XA_FLAG_COMPLETE)
smb_xa_close(sr->r_xa);
@@ -590,9 +587,7 @@
ASSERT(sr->tid_tree == 0);
ASSERT(sr->uid_user == 0);
ASSERT(sr->fid_ofile == 0);
- ASSERT(sr->sid_odir == 0);
sr->smb_fid = (uint16_t)-1;
- sr->smb_sid = (uint16_t)-1;
/* temporary until we identify a user */
sr->user_cr = kcred;
@@ -1173,15 +1168,6 @@
(void) smb_ofile_release(of);
}
-void
-smbsr_disconnect_dir(smb_request_t *sr)
-{
- smb_odir_t *od = sr->sid_odir;
-
- sr->sid_odir = NULL;
- smb_odir_release(od);
-}
-
static int
is_andx_com(unsigned char com)
{
--- a/usr/src/uts/common/fs/smbsrv/smb_find.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_find.c Sun Feb 01 19:44:54 2009 -0700
@@ -19,196 +19,362 @@
* 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 "@(#)smb_find.c 1.7 08/07/30 SMI"
-
-#include <smbsrv/smb_incl.h>
-
/*
- * smb_com_find
+ * smb_com_search
+ * smb_com_find, smb_com_find_close
+ * smb_find_unique
*
- * Request Format: (same as core Search Protocol - "Find First" form)
+ * These commands are used for directory searching. They share the same
+ * message formats, defined below:
*
- * Client Request Description
- * ================================== =================================
+ * Client Request Description
+ * ---------------------------------- ---------------------------------
*
- * BYTE smb_wct; value = 2
- * WORD smb_count; max number of entries to find
- * WORD smb_attr; search attribute
- * WORD smb_bcc; minimum value = 5
- * BYTE smb_ident1; ASCII (04)
- * BYTE smb_pathname[]; filename (may contain global characters)
- * BYTE smb_ident2; Variable Block (05)
- * WORD smb_keylen; resume key length (zero if "Find First")
- * BYTE smb_resumekey[*]; "Find Next" key, * = value of smb_keylen
- *
- * Response Format: (same as core Search Protocol)
+ * UCHAR WordCount; Count of parameter words = 2
+ * USHORT MaxCount; Number of dir. entries to return
+ * USHORT SearchAttributes;
+ * USHORT ByteCount; Count of data bytes; min = 5
+ * UCHAR BufferFormat1; 0x04 -- ASCII
+ * UCHAR FileName[]; File name, may be null
+ * UCHAR BufferFormat2; 0x05 -- Variable block
+ * USHORT ResumeKeyLength; Length of resume key, may be 0
+ * UCHAR ResumeKey[]; Resume key
*
- * Server Response Description
- * ================================== =================================
- * BYTE smb_wct; value = 1
- * WORD smb_count; number of entries found
- * WORD smb_bcc; minimum value = 3
- * BYTE smb_ident; Variable Block (05)
- * WORD smb_datalen; data length
- * BYTE smb_data[*]; directory entries
+ * FileName specifies the file to be sought. SearchAttributes indicates
+ * the attributes that the file must have. If SearchAttributes is
+ * zero then only normal files are returned. If the system file, hidden or
+ * directory attributes are specified then the search is inclusive - both the
+ * specified type(s) of files and normal files are returned. If the volume
+ * label attribute is specified then the search is exclusive, and only the
+ * volume label entry is returned.
+ *
+ * MaxCount specifies the number of directory entries to be returned.
+ *
+ * Server Response Description
+ * ---------------------------------- ---------------------------------
*
- * Directory Information Entry (dir_info) Format: (same as core Search Protocol)
+ * UCHAR WordCount; Count of parameter words = 1
+ * USHORT Count; Number of entries returned
+ * USHORT ByteCount; Count of data bytes; min = 3
+ * UCHAR BufferFormat; 0x05 -- Variable block
+ * USHORT DataLength; Length of data
+ * UCHAR DirectoryInformationData[]; Data
*
- * BYTE find_buf_reserved[21]; reserved (resume_key)
- * BYTE find_buf_attr; attribute
- * WORD find_buf_time; modification time (hhhhh mmmmmm xxxxx)
- * where 'xxxxx' is in 2 second increments
- * WORD find_buf_date; modification date (yyyyyyy mmmm ddddd)
- * DWORD find_buf_size; file size
- * STRING find_buf_pname[13]; file name -- ASCII (null terminated)
+ * The response will contain one or more directory entries as determined by
+ * the Count field. No more than MaxCount entries will be returned. Only
+ * entries that match the sought FileName and SearchAttributes combination
+ * will be returned.
+ *
+ * ResumeKey must be null (length = 0) on the initial search request.
+ * Subsequent search requests intended to continue a search must contain
+ * the ResumeKey field extracted from the last directory entry of the
+ * previous response. ResumeKey is self-contained, for calls containing
+ * a non-zero ResumeKey neither the SearchAttributes or FileName fields
+ * will be valid in the request. ResumeKey has the following format:
+ *
+ * Resume Key Field Description
+ * ---------------------------------- ---------------------------------
*
- * The resume_key has the following format:
+ * UCHAR Reserved; bit 7 - consumer use
+ * bits 5,6 - system use (must preserve)
+ * bits 0-4 - server use (must preserve)
+ * UCHAR FileName[11]; Name of the returned file
+ * UCHAR ReservedForServer[5]; Client must not modify
+ * byte 0 - uniquely identifies find
+ * through find_close
+ * bytes 1-4 - available for server use
+ * (must be non-zero)
+ * UCHAR ReservedForConsumer[4]; Server must not modify
+ *
+ * FileName is 8.3 format, with the three character extension left
+ * justified into FileName[9-11].
*
- * BYTE sr_res; reserved:
- * bit 7 - reserved for consumer use
- * bit 5,6 - reserved for system use
- * (must be preserved)
- * bits 0-4 - reserved for server
- * (must be preserved)
- * BYTE sr_name[11]; pathname sought.
- * Format: 1-8 character file name,
- * left justified 0-3 character extension,
- * BYTE sr_findid[1]; uniquely identifies find through
- * find_close
- * BYTE sr_server[4]; available for server use
- * (must be non-zero)
- * BYTE sr_res[4]; reserved for consumer use
+ * There may be multiple matching entries in response to a single request
+ * as wildcards are supported in the last component of FileName of the
+ * initial request.
+ *
+ * Returned directory entries in the DirectoryInformationData field of the
+ * response each have the following format:
+ *
+ * Directory Information Field Description
+ * ---------------------------------- ---------------------------------
*
- * Service:
+ * SMB_RESUME_KEY ResumeKey; Described above
+ * UCHAR FileAttributes; Attributes of the found file
+ * SMB_TIME LastWriteTime; Time file was last written
+ * SMB_DATE LastWriteDate; Date file was last written
+ * ULONG FileSize; Size of the file
+ * UCHAR FileName[13]; ASCII, space-filled null terminated
+ *
+ * FileName must conform to 8.3 rules, and is padded after the extension
+ * with 0x20 characters if necessary.
*
- * The Find protocol finds the directory entry or group of entries matching the
- * specified file pathname. The filename portion of the pathname may contain
- * global (wild card) characters.
+ * As can be seen from the above structure, these commands cannot return
+ * long filenames, and cannot return UNICODE filenames.
+ *
+ * Files which have a size greater than 2^32 bytes should have the least
+ * significant 32 bits of their size returned in FileSize.
*
- * The Find protocol is used to match the find OS/2 system call. The protocols
- * "Find", "Find_Unique" and "Find_Close" are methods of reading (or searching)
- * a directory. These protocols may be used in place of the core "Search"
- * protocol when LANMAN 1.0 dialect has been negotiated. There may be cases
- * where the Search protocol will still be used.
+ * smb_com_search
+ * --------------
+ *
+ * If the client is prior to the LANMAN1.0 dialect, the returned FileName
+ * should be uppercased.
+ * If the client has negotiated a dialect prior to the LANMAN1.0 dialect,
+ * or if bit0 of the Flags2 SMB header field of the request is clear,
+ * the returned FileName should be uppercased.
*
- * The format of the Find protocol is the same as the core "Search" protocol.
- * The difference is that the directory is logically Opened with a Find protocol
- * and logically closed with the Find Close protocol. This allows the Server to
- * make better use of its resources. Search buffers are thus held (allowing
- * search resumption via presenting a "resume_key") until a Find Close protocol
- * is received. The sr_findid field of each resume key is a unique identifier
- * (within the session) of the search from "Find" through "Find close". Thus if
- * the consumer does "Find ahead", any find buffers containing resume keys with
- * the matching find id may be released when the Find Close is requested.
+ * SMB_COM_SEARCH terminates when either the requested maximum number of
+ * entries that match the named file are found, or the end of directory is
+ * reached without the maximum number of matches being found. A response
+ * containing no entries indicates that no matching entries were found
+ * between the starting point of the search and the end of directory.
+ *
+ *
+ * The find, find_close and find_unique protocols may be used in place of
+ * the core "search" protocol when LANMAN 1.0 dialect has been negotiated.
*
- * As is true of a failing open, if a Find request (Find "first" request where
+ * smb_com_find
+ * ------------
+ *
+ * The find protocol is used to match the find OS/2 system call.
+ *
+ * The format of the find protocol is the same as the core "search" protocol.
+ * The difference is that the directory is logically Opened with a find protocol
+ * and logically closed with the find close protocol.
+ * As is true of a failing open, if a find request (find "first" request where
* resume_key is null) fails (no entries are found), no find close protocol is
* expected.
*
- * If no global characters are present, a "Find Unique" protocol should be used
+ * If no global characters are present, a "find unique" protocol should be used
* (only one entry is expected and find close need not be sent).
*
- * The file path name in the request specifies the file to be sought. The
- * attribute field indicates the attributes that the file must have. If the
- * attribute is zero then only normal files are returned. If the system file,
- * hidden or directory attributes are specified then the search is inclusive --
- * both the specified type(s) of files and normal files are returned. If the
- * volume label attribute is specified then the search is exclusive, and only
- * the volume label entry is returned
- *
- * The max-count field specifies the number of directory entries to be returned.
- * The response will contain zero or more directory entries as determined by the
- * count-returned field. No more than max-count entries will be returned. Only
- * entries that match the sought filename/attribute will be returned.
- *
- * The resume_key field must be null (length = 0) on the initial ("Find First")
- * find request. Subsequent find requests intended to continue a search must
- * contain the resume_key field extracted from the last directory entry of the
- * previous response. The resume_key field is self-contained, for on calls
- * containing a resume_key neither the attribute or pathname fields will be
- * valid in the request. A find request will terminate when either the
- * requested maximum number of entries that match the named file are found, or
- * the end of directory is reached without the maximum number of matches being
- * found. A response containing no entries indicates that no matching entries
- * were found between the starting point of the search and the end of directory.
+ * A find request will terminate when either the requested maximum number of
+ * entries that match the named file are found, or the end of directory is
+ * reached without the maximum number of matches being found. A response
+ * containing no entries indicates that no matching entries were found between
+ * the starting point of the search and the end of directory.
*
- * There may be multiple matching entries in response to a single request as
- * Find supports "wild cards" in the file name (last component of the pathname).
- * "?" is the wild single characters, "*" or "null" will match any number of
- * filename characters within a single part of the filename component. The
- * filename is divided into two parts -- an eight character name and a three
- * character extension. The name and extension are divided by a ".".
- *
- * If a filename part commences with one or more "?"s then exactly that number
- * of characters will be matched by the Wild Cards, e.g., "??x" will equal "abx"
- * but not "abcx" or "ax". When a filename part has trailing "?"s then it will
- * match the specified number of characters or less, e.g., "x??" will match
- * "xab", "xa" and "x", but not "xabc". If only "?"s are present in the filename
- * part, then it is handled as for trailing "?"s "*" or "null" match entire
- * pathname parts, thus "*.abc" or ".abc" will match any file with an extension
- * of "abc". "*.*", "*" or "null" will match all files in a directory.
- *
- * Unprotected servers require the requester to have read permission on the
- * subtree containing the directory searched (the share specifies read
- * permission).
- *
- * Protected servers require the requester to have permission to search the
- * specified directory.
- *
- * If a Find requests more data than can be placed in a message of the
+ * If a find requests more data than can be placed in a message of the
* max-xmit-size for the TID specified, the server will return only the number
* of entries which will fit.
*
- * The number of entries returned will be the minimum of:
- * 1. The number of entries requested.
- * 2. The number of (complete) entries that will fit in the negotiated SMB
- * buffer.
- * 3. The number of entries that match the requested name pattern and
- * attributes.
+ *
+ * smb_com_find_close
+ * ------------------
+ *
+ * The find close protocol is used to match the find close OS/2 system call.
+ *
+ * Whereas the first find protocol logically opens the directory, subsequent
+ * find protocols presenting a resume_key further "read" the directory, the
+ * find close protocol "closes" the directory allowing the server to free any
+ * resources held in support of the directory search.
*
- * The error ERRnofiles set in smb_err field of the response header or a zero
- * value in smb_count of the response indicates no matching entry was found.
+ * In our implementation this translates to closing the odir.
+ *
+ *
+ * smb_com_find_unique
+ * -------------------
*
- * The resume search key returned along with each directory entry is a server
- * defined key which when returned in the Find Next protocol, allows the
- * directory search to be resumed at the directory entry fol lowing the one
- * denoted by the resume search key.
+ * The format of the find unique protocol is the same as the core "search"
+ * protocol. The difference is that the directory is logically opened, any
+ * matching entries returned, and then the directory is logically closed.
+ *
+ * The resume search key key will be returned as in the find protocol and
+ * search protocol however it may NOT be returned to continue the search.
+ * Only one buffer of entries is expected and find close need not be sent.
*
- * The date is in the following format:
- * bits:
- * 1 1 1 1 1 1
- * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * y y y y y y y m m m m d d d d d
- * where:
- * y - bit of year 0-119 (1980-2099)
- * m - bit of month 1-12
- * d - bit of day 1-31
- *
- * The time is in the following format:
- * bits:
- * 1 1 1 1 1 1
- * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * h h h h h m m m m m m x x x x x
- * where:
- * h - bit of hour (0-23)
- * m - bit of minute (0-59)
- * x - bit of 2 second increment
- *
- * Find may generate the following errors.
- * ERRDOS/ERRnofiles
- * ERRDOS/ERRbadpath
- * ERRDOS/ERRnoaccess
- * ERRDOS/ERRbadaccess
- * ERRDOS/ERRbadshare
- * ERRSRV/ERRerror
- * ERRSRV/ERRaccess
- * ERRSRV/ERRinvnid
+ * If a find unique requests more data than can be placed in a message of the
+ * max-xmit-size for the TID specified, the server will abort the virtual
+ * circuit to the consumer.
*/
+
+#include <smbsrv/smb_incl.h>
+
+/* *** smb_com_search *** */
+
+smb_sdrc_t
+smb_pre_search(smb_request_t *sr)
+{
+ DTRACE_SMB_1(op__Search__start, smb_request_t *, sr);
+ return (SDRC_SUCCESS);
+}
+
+void
+smb_post_search(smb_request_t *sr)
+{
+ DTRACE_SMB_1(op__Search__done, smb_request_t *, sr);
+}
+
+smb_sdrc_t
+smb_com_search(smb_request_t *sr)
+{
+ int rc;
+ uint16_t count, maxcount, index;
+ uint16_t sattr, odid;
+ uint16_t key_len;
+ uint32_t client_key;
+ char name[SMB_SHORTNAMELEN];
+ char *path;
+ unsigned char resume_char;
+ unsigned char type;
+ boolean_t find_first, to_upper;
+ smb_tree_t *tree;
+ smb_odir_t *od;
+ smb_fileinfo_t fileinfo;
+ smb_odir_resume_t odir_resume;
+ boolean_t eos;
+
+ to_upper = B_FALSE;
+ if ((sr->session->dialect <= LANMAN1_0) ||
+ ((sr->smb_flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES) == 0)) {
+ to_upper = B_TRUE;
+ }
+
+ /* We only handle 8.3 name here */
+ sr->smb_flg2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES;
+ sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE;
+
+ if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
+ return (SDRC_ERROR);
+
+ rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len);
+ if ((rc != 0) || (type != 0x05))
+ return (SDRC_ERROR);
+
+ tree = sr->tid_tree;
+
+ /* Volume information only */
+ if ((sattr == FILE_ATTRIBUTE_VOLUME) && (key_len != 21)) {
+ (void) memset(name, ' ', sizeof (name));
+ (void) strncpy(name, tree->t_volume, sizeof (name));
+
+ if (key_len >= 21) {
+ (void) smb_mbc_decodef(&sr->smb_data, "17.l",
+ &client_key);
+ } else {
+ client_key = 0;
+ }
+
+ (void) smb_mbc_encodef(&sr->reply, "bwwbwb11c5.lb8.13c",
+ 1, 0, VAR_BCC, 5, 0, 0, path+1,
+ client_key, sattr, name);
+
+ rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8;
+ (void) smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
+ 1, 1, rc+3, 5, rc);
+
+ return (SDRC_SUCCESS);
+ }
+
+ if ((key_len != 0) && (key_len != 21))
+ return (SDRC_ERROR);
+
+ find_first = (key_len == 0);
+ resume_char = 0;
+ client_key = 0;
+
+ if (find_first) {
+ /* NT interprets NULL filename as "\" */
+ if (strlen(path) == 0)
+ path = "\\";
+
+ odid = smb_odir_open(sr, path, sattr);
+ if (odid == 0) {
+ if (sr->smb_error.status == NT_STATUS_ACCESS_DENIED)
+ smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
+ ERRDOS, ERROR_NO_MORE_FILES);
+ return (SDRC_ERROR);
+ }
+ } else {
+ if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
+ &resume_char, &index, &odid, &client_key) != 0) {
+ return (SDRC_ERROR);
+ }
+ }
+
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
+ return (SDRC_ERROR);
+ }
+
+ if (!find_first) {
+ odir_resume.or_type = SMB_ODIR_RESUME_IDX;
+ odir_resume.or_idx = index;
+ smb_odir_resume_at(od, &odir_resume);
+ }
+
+ (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0);
+
+ rc = 0;
+ index = 0;
+ count = 0;
+ if (maxcount > SMB_MAX_SEARCH)
+ maxcount = SMB_MAX_SEARCH;
+
+ while (count < maxcount) {
+ rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
+ if ((rc != 0 || (eos == B_TRUE)))
+ break;
+
+ if (smb_is_dot_or_dotdot(fileinfo.fi_name))
+ continue;
+
+ if (*fileinfo.fi_shortname == NULL) {
+ (void) strlcpy(fileinfo.fi_shortname,
+ fileinfo.fi_name, SMB_SHORTNAMELEN - 1);
+ if (to_upper)
+ (void) utf8_strupr(fileinfo.fi_shortname);
+ }
+
+ (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c",
+ resume_char,
+ fileinfo.fi_name83, fileinfo.fi_name83+9,
+ index, odid, client_key,
+ fileinfo.fi_dosattr & 0xff,
+ smb_gmt2local(sr, fileinfo.fi_mtime.tv_sec),
+ (int32_t)fileinfo.fi_size,
+ fileinfo.fi_shortname);
+
+ smb_odir_save_cookie(od, index, fileinfo.fi_cookie);
+
+ count++;
+ index++;
+ }
+ smb_odir_release(od);
+
+ if (rc != 0) {
+ smb_odir_close(od);
+ return (SDRC_ERROR);
+ }
+
+ if (count == 0 && find_first) {
+ smb_odir_close(od);
+ smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
+ ERRDOS, ERROR_NO_MORE_FILES);
+ return (SDRC_ERROR);
+ }
+
+ rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8;
+ if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
+ 1, count, rc+3, 5, rc) < 0) {
+ smb_odir_close(od);
+ return (SDRC_ERROR);
+ }
+
+ return (SDRC_SUCCESS);
+}
+
+
+/* *** smb_com_find *** */
+
smb_sdrc_t
smb_pre_find(smb_request_t *sr)
{
@@ -226,17 +392,19 @@
smb_com_find(smb_request_t *sr)
{
int rc;
- unsigned short sattr, count, maxcount;
+ uint16_t count, maxcount, index;
+ uint16_t sattr, odid;
+ uint16_t key_len;
+ uint32_t client_key;
+ smb_odir_t *od;
+ smb_fileinfo_t fileinfo;
+ boolean_t eos;
+
char *path;
unsigned char resume_char;
- uint32_t client_key;
- uint16_t index;
- uint32_t cookie;
- struct smb_node *node;
unsigned char type;
- unsigned short key_len;
- smb_odir_context_t *pc;
boolean_t find_first = B_TRUE;
+ smb_odir_resume_t odir_resume;
if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
return (SDRC_ERROR);
@@ -245,78 +413,78 @@
if ((rc != 0) || (type != 0x05))
return (SDRC_ERROR);
- if (key_len == 0) { /* begin search */
- if (smb_rdir_open(sr, path, sattr) != 0)
+ if ((key_len != 0) && (key_len != 21))
+ return (SDRC_ERROR);
+
+ find_first = (key_len == 0);
+ resume_char = 0;
+ client_key = 0;
+
+ if (find_first) {
+ odid = smb_odir_open(sr, path, sattr);
+ if (odid == 0)
return (SDRC_ERROR);
- cookie = 0;
- } else if (key_len == 21) {
- sr->smb_sid = 0;
+ } else {
if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
- &resume_char, &index, &sr->smb_sid, &client_key) != 0) {
- /* We don't know which rdir to close */
+ &resume_char, &index, &odid, &client_key) != 0) {
return (SDRC_ERROR);
}
+ }
- sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree,
- sr->smb_sid);
- if (sr->sid_odir == NULL) {
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
- ERRDOS, ERRbadfid);
- return (SDRC_ERROR);
- }
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
+ return (SDRC_ERROR);
+ }
- cookie = sr->sid_odir->d_cookies[index];
- if (cookie != 0)
- find_first = B_FALSE;
- } else {
- /* We don't know which rdir to close */
- return (SDRC_ERROR);
+ if (!find_first) {
+ odir_resume.or_type = SMB_ODIR_RESUME_IDX;
+ odir_resume.or_idx = index;
+ smb_odir_resume_at(od, &odir_resume);
}
(void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0);
- pc = kmem_zalloc(sizeof (smb_odir_context_t), KM_SLEEP);
- pc->dc_cookie = cookie;
+ rc = 0;
index = 0;
count = 0;
- node = NULL;
- rc = 0;
-
if (maxcount > SMB_MAX_SEARCH)
maxcount = SMB_MAX_SEARCH;
while (count < maxcount) {
- if ((rc = smb_rdir_next(sr, &node, pc)) != 0)
+ rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
+ if ((rc != 0 || (eos == B_TRUE)))
break;
+ if (*fileinfo.fi_shortname == NULL) {
+ (void) strlcpy(fileinfo.fi_shortname,
+ fileinfo.fi_name, SMB_SHORTNAMELEN - 1);
+ }
+
(void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c",
resume_char,
- pc->dc_name83, pc->dc_name83+9,
- index, sr->smb_sid, client_key,
- pc->dc_dattr & 0xff,
- smb_gmt2local(sr, pc->dc_attr.sa_vattr.va_mtime.tv_sec),
- (int32_t)smb_node_get_size(node, &pc->dc_attr),
- (*pc->dc_shortname) ? pc->dc_shortname :
- pc->dc_name);
+ fileinfo.fi_name83, fileinfo.fi_name83+9,
+ index, odid, client_key,
+ fileinfo.fi_dosattr & 0xff,
+ smb_gmt2local(sr, fileinfo.fi_mtime.tv_sec),
+ (int32_t)fileinfo.fi_size,
+ fileinfo.fi_shortname);
- smb_node_release(node);
- node = NULL;
- sr->sid_odir->d_cookies[index] = pc->dc_cookie;
+ smb_odir_save_cookie(od, index, fileinfo.fi_cookie);
+
count++;
index++;
}
-
- kmem_free(pc, sizeof (smb_odir_context_t));
+ smb_odir_release(od);
- if ((rc != 0) && (rc != ENOENT)) {
- /* returned error by smb_rdir_next() */
- smb_rdir_close(sr);
- smbsr_errno(sr, rc);
+ if (rc != 0) {
+ smb_odir_close(od);
return (SDRC_ERROR);
}
if (count == 0 && find_first) {
- smb_rdir_close(sr);
+ smb_odir_close(od);
smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
ERRDOS, ERROR_NO_MORE_FILES);
return (SDRC_ERROR);
@@ -325,91 +493,16 @@
rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8;
if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
1, count, rc+3, 5, rc) < 0) {
- smb_rdir_close(sr);
+ smb_odir_close(od);
return (SDRC_ERROR);
}
return (SDRC_SUCCESS);
}
-/*
- * smb_com_find_close
- *
- * Request Format: (same as core Search Protocol - "Find Next" form)
- *
- * Client Request Description
- * ================================== =================================
- *
- * BYTE smb_wct; value = 2
- * WORD smb_count; max number of entries to find
- * WORD smb_attr; search attribute
- * WORD smb_bcc; minimum value = 5
- * BYTE smb_ident1; ASCII (04)
- * BYTE smb_pathname[]; null (may contain only null)
- * BYTE smb_ident2; Variable Block (05)
- * WORD smb_keylen; resume (close) key length
- * (may not be zero)
- * BYTE smb_resumekey[*]; "Find Close" key
- * (* = value of smb_keylen)
- *
- * Response Format: (same format as core Search Protocol)
- *
- * Server Response Description
- * ================================== =================================
- *
- * BYTE smb_wct; value = 1
- * WORD smb_reserved; reserved
- * WORD smb_bcc; value = 3
- * BYTE smb_ident; Variable Block (05)
- * WORD smb_datalen; data length (value = 0)
- *
- * The resume_key (or close key) has the following format:
- *
- * BYTE sr_res; reserved:
- * bit 7 - reserved for consumer use
- * bit 5,6 - reserved for system use
- * (must be preserved)
- * bits 0-4 - rsvd for server
- * (must be preserved by consumer)
- * BYTE sr_name[11]; pathname sought.
- * Format: 1-8 character file name,
- * left justified 0-3 character extension,
- * left justified (in last 3 chars)
- * BYTE sr_findid[1]; uniquely identifies find
- * through find_close
- * BYTE sr_server[4]; available for server use
- * (must be non-zero)
- * BYTE sr_res[4]; reserved for consumer use
- *
- * Service:
- *
- * The Find_Close protocol closes the association between a Find id
- * returned (in the resume_key) by the Find protocol and the directory
- * search.
- *
- * Whereas the First Find protocol logically opens the directory,
- * subsequent find protocols presenting a resume_key further "read" the
- * directory, the Find Close protocol "closes" the directory allowing the
- * server to free any resources held in support of the directory search.
- *
- * The Find Close protocol is used to match the find Close OS/2
- * system call. The protocols "Find", "Find Unique" and "Find Close" are
- * methods of reading (or searching) a directory. These protocols may
- * be used in place of the core "Search" protocol when LANMAN 1.0 dialect has
- * been negotiated. There may be cases where the Search protocol will still be
- * used.
- *
- * Although only the find id portion the resume key should be
- * required to identify the search being ter minated, the entire
- * resume_key as returned in the previous Find, either a "Find First" or "Find
- * Next" is sent to the server in this protocol.
- *
- * Find Close may generate the following errors:
- *
- * ERRDOS/ERRbadfid
- * ERRSRV/ERRerror
- * ERRSRV/ERRinvnid
- */
+
+/* *** smb_com_find_close *** */
+
smb_sdrc_t
smb_pre_find_close(smb_request_t *sr)
{
@@ -426,14 +519,15 @@
smb_sdrc_t
smb_com_find_close(smb_request_t *sr)
{
- unsigned short sattr, maxcount;
- char *path;
- unsigned char resume_char;
- uint32_t resume_key;
- uint16_t index;
- unsigned char type;
- unsigned short key_len;
- int rc;
+ int rc;
+ uint16_t maxcount, index;
+ uint16_t sattr, odid;
+ uint16_t key_len;
+ uint32_t client_key;
+ char *path;
+ unsigned char resume_char;
+ unsigned char type;
+ smb_odir_t *od;
if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
return (SDRC_ERROR);
@@ -442,31 +536,132 @@
if ((rc != 0) || (type != 0x05))
return (SDRC_ERROR);
- if (key_len == 0) { /* begin search */
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
+ if (key_len == 0) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
+ return (SDRC_ERROR);
+ } else if (key_len != 21) {
+ return (SDRC_ERROR);
+ }
+
+ odid = 0;
+ if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
+ &resume_char, &index, &odid, &client_key) != 0) {
+ return (SDRC_ERROR);
+ }
+
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
return (SDRC_ERROR);
}
- if (key_len == 21) {
- sr->smb_sid = 0;
- if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
- &resume_char, &index, &sr->smb_sid, &resume_key) != 0) {
- return (SDRC_ERROR);
+ smb_odir_release(od);
+ smb_odir_close(od);
+
+ if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0))
+ return (SDRC_ERROR);
+
+ return (SDRC_SUCCESS);
+}
+
+
+/* *** smb_com_find_unique *** */
+
+smb_sdrc_t
+smb_pre_find_unique(smb_request_t *sr)
+{
+ DTRACE_SMB_1(op__FindUnique__start, smb_request_t *, sr);
+ return (SDRC_SUCCESS);
+}
+
+void
+smb_post_find_unique(smb_request_t *sr)
+{
+ DTRACE_SMB_1(op__FindUnique__done, smb_request_t *, sr);
+}
+
+smb_sdrc_t
+smb_com_find_unique(struct smb_request *sr)
+{
+ int rc;
+ uint16_t count, maxcount, index;
+ uint16_t sattr, odid;
+ char *path;
+ unsigned char resume_char = '\0';
+ uint32_t client_key = 0;
+ smb_odir_t *od;
+ smb_fileinfo_t fileinfo;
+ boolean_t eos;
+ struct vardata_block *vdb;
+
+ if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
+ return (SDRC_ERROR);
+
+ vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP);
+ if ((smbsr_decode_data(sr, "%AV", sr, &path, vdb) != 0) ||
+ (vdb->len != 0)) {
+ kmem_free(vdb, sizeof (struct vardata_block));
+ return (SDRC_ERROR);
+ }
+ kmem_free(vdb, sizeof (struct vardata_block));
+
+ (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0);
+
+ odid = smb_odir_open(sr, path, sattr);
+ if (odid == 0)
+ return (SDRC_ERROR);
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL)
+ return (SDRC_ERROR);
+
+ rc = 0;
+ count = 0;
+ index = 0;
+ if (maxcount > SMB_MAX_SEARCH)
+ maxcount = SMB_MAX_SEARCH;
+
+ while (count < maxcount) {
+ rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
+ if ((rc != 0 || (eos == B_TRUE)))
+ break;
+
+ if (*fileinfo.fi_shortname == NULL) {
+ (void) strlcpy(fileinfo.fi_shortname,
+ fileinfo.fi_name, SMB_SHORTNAMELEN - 1);
}
- sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree,
- sr->smb_sid);
- if (sr->sid_odir == NULL) {
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
- ERRDOS, ERRbadfid);
- return (SDRC_ERROR);
- }
- } else {
+ (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c",
+ resume_char,
+ fileinfo.fi_name83, fileinfo.fi_name83+9,
+ index, odid, client_key,
+ fileinfo.fi_dosattr & 0xff,
+ smb_gmt2local(sr, fileinfo.fi_mtime.tv_sec),
+ (int32_t)fileinfo.fi_size,
+ fileinfo.fi_shortname);
+
+ count++;
+ index++;
+ }
+
+ smb_odir_release(od);
+ smb_odir_close(od);
+
+ if (rc != 0)
+ return (SDRC_ERROR);
+
+ if (count == 0) {
+ smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
+ ERRDOS, ERROR_NO_MORE_FILES);
return (SDRC_ERROR);
}
- smb_rdir_close(sr);
- if (smbsr_encode_result(sr, 1, 3, "bwwbw", 1, 0, 3, 5, 0))
+ rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8;
+ if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset,
+ "bwwbw", 1, count, rc+3, 5, rc) < 0) {
return (SDRC_ERROR);
+ }
+
return (SDRC_SUCCESS);
}
--- a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c Sun Feb 01 15:33:03 2009 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +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.
- */
-
-#pragma ident "@(#)smb_find_unique.c 1.6 08/07/30 SMI"
-
-#include <smbsrv/smb_incl.h>
-
-/*
- * Request Format: (same as core Search Protocol - "Find First" form)
- *
- * Client Request Description
- * ================================== =================================
- *
- * BYTE smb_wct; value = 2
- * WORD smb_count; max number of entries to find
- * WORD smb_attr; search attribute
- * WORD smb_bcc; minimum value = 5
- * BYTE smb_ident1; ASCII (04)
- * BYTE smb_pathname[]; filename (may contain global characters)
- * BYTE smb_ident2; Variable Block (05)
- * WORD smb_keylen; must be zero ("Find First" only)
- *
- * Response Format: (same as core Search Protocol)
- *
- * Server Response Description
- * ================================== =================================
- * BYTE smb_wct; value = 1
- * WORD smb_count; number of entries found
- * WORD smb_bcc; minimum value = 3
- * BYTE smb_ident; Variable Block (05)
- * WORD smb_datalen; data length
- * BYTE smb_data[*]; directory entries
- *
- * Directory Information Entry (dir_info) Format: (same as core Search Protocol)
- *
- * BYTE find_buf_reserved[21]; reserved (resume_key)
- * BYTE find_buf_attr; attribute
- * WORD find_buf_time; modification time (hhhhh mmmmmm xxxxx)
- * where 'xxxxx' is in 2 second increments
- * WORD find_buf_date; modification date (yyyyyyy mmmm ddddd)
- * DWORD find_buf_size; file size
- * STRING find_buf_pname[13]; file name -- ASCII (null terminated)
- *
- * The resume_key has the following format:
- *
- * BYTE sr_res; reserved:
- * bit 7 - reserved for consumer use
- * bit 5,6 - reserved for system use
- * (must be preserved)
- * bits 0-4 - reserved for server
- * (must be preserved)
- * BYTE sr_name[11]; pathname sought.
- * Format: 1-8 character file name,
- * left justified 0-3 character extension,
- * BYTE sr_findid[1]; uniquely identifies find through
- * find_close
- * BYTE sr_server[4]; available for server use
- * (must be non-zero)
- * BYTE sr_res[4]; reserved for consumer use
- *
- * Service:
- *
- * The Find protocol finds the directory entry or group of entries matching the
- * specified file pathname. The filename portion of the pathname may contain
- * global (wild card) characters. The search may not be resumed and no Find
- * Close protocol is expected.
- *
- * The Find protocol is used to match the find OS/2 system call. The protocols
- * "Find", "Find_Unique" and "Find_Close" are methods of reading (or searching)
- * a directory. These protocols may be used in place of the core "Search"
- * protocol when LANMAN 1.0 dialect has been negotiated. There may be cases
- * where the Search protocol will still be used.
- *
- * The format of the Find Unique protocol is the same as the core "Search"
- * protocol. The difference is that the directory is logically opened ,
- * any matching entries returned, and then the directory is logically
- * closed.
- *
- * This allows the Server to make better use of its resources. No Search buffers
- * are held (search resumption via presenting a "resume_key" will not be
- * allowed).
- *
- * Only one buffer of entries is expected and find close need not be sent).
- *
- * The file path name in the request specifies the file to be
- * sought. The attribute field indicates the attributes that the file
- * must have. If the attribute is zero then only normal files are
- * returned. If the system file, hidden or directory attributes are
- * specified then the search is inclusive -- both the specified type(s)
- * of files and normal files are returned. If the volume label attribute
- * is specified then the search is exclusive, and only the volume label entry
- * is returned
- *
- * The max-count field specifies the number of directory entries to be
- * returned. The response will contain zero or more directory entries
- * as determined by the count-returned field. No more than max-count
- * entries will be returned. Only entries that match the sought
- * filename/attribute will be returned.
- *
- * The resume_key field must be null (length = 0).
- *
- * A Find_Unique request will terminate when either the requested maximum
- * number of entries that match the named file are found, or the end
- * of directory is reached without the maximum number of matches being
- * found. A response containing no entries indicates that no matching
- * entries were found between the starting point of the search and the end of
- * directory.
- *
- * There may be multiple matching entries in response to a single
- * request as Find Unique supports "wild cards" in the file name (last
- * component of the pathname). "?" is the wild card for single
- * characters, "*" or "null" will match any number of filename characters
- * within a single part of the filename component. The filename is
- * divided into two parts -- an eight character name and a three
- * character extension. The name and extension are divided by a ".".
- *
- * If a filename part commences with one or more "?"s then exactly
- * that number of characters will be matched by the Wild Cards, e.g.,
- * "??x" will equal "abx" but not "abcx" or "ax". When a filename part has
- * trailing "?"s then it will match the specified number of characters
- * or less, e.g., "x??" will match "xab", "xa" and "x", but not "xabc". If
- * only "?"s are present in the filename part, then it is handled as
- * for trailing "?"s
- *
- * "*" or "null" match entire pathname parts, thus "*.abc" or ".abc" will
- * match any file with an extension of "abc". "*.*", "*" or "null" will
- * match all files in a directory.
- *
- * Unprotected servers require the requester to have read permission on the
- * subtree containing the directory searched, the share specifies read
- * permission.
- *
- * Protected servers require the requester to have permission to search the
- * specified directory.
- *
- * If a Find Unique requests more data than can be placed in a
- * message of the max-xmit-size for the TID specified, the server will
- * abort the virtual circuit to the consumer.
- *
- * The number of entries returned will be the minimum of:
- *
- * 1. The number of entries requested.
- * 2. The number of complete entries that will fit in the
- * negotiated SMB buffer.
- * 3. The number of entries that match the requested name pattern and
- * attributes.
- *
- * The error ERRnofiles set in smb_err field of the response header or a zero
- * value in smb_count of the response indicates no matching entry was found.
- *
- * The resume search key returned along with each directory entry is a server
- * defined key. This key will be returned as in the Find protocol and Search
- * protocol however it may NOT be returned to continue the search.
- *
- * The date is in the following format:
- * bits:
- * 1 1 1 1 1 1
- * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * y y y y y y y m m m m d d d d d
- * where:
- * y - bit of year 0-119 (1980-2099)
- * m - bit of month 1-12
- * d - bit of day 1-31
- *
- * The time is in the following format:
- * bits:
- * 1 1 1 1 1 1
- * 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * h h h h h m m m m m m x x x x x
- * where:
- * h - bit of hour (0-23)
- * m - bit of minute (0-59)
- * x - bit of 2 second increment
- *
- * Find Unique may generate the following errors.
- * ERRDOS/ERRnofiles
- * ERRDOS/ERRbadpath
- * ERRDOS/ERRnoaccess
- * ERRDOS/ERRbadaccess
- * ERRDOS/ERRbadshare
- * ERRSRV/ERRerror
- * ERRSRV/ERRaccess
- * ERRSRV/ERRinvnid
- */
-smb_sdrc_t
-smb_pre_find_unique(smb_request_t *sr)
-{
- DTRACE_SMB_1(op__FindUnique__start, smb_request_t *, sr);
- return (SDRC_SUCCESS);
-}
-
-void
-smb_post_find_unique(smb_request_t *sr)
-{
- DTRACE_SMB_1(op__FindUnique__done, smb_request_t *, sr);
-}
-
-smb_sdrc_t
-smb_com_find_unique(struct smb_request *sr)
-{
- int rc;
- unsigned short sattr, count, maxcount;
- char *path;
- struct vardata_block *vdb;
- struct smb_node *node;
- uint16_t index;
- unsigned char resume_char = '\0';
- uint32_t client_key = 0;
- smb_odir_context_t *pc;
-
- vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP);
- if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_ERROR);
- }
-
- if (smbsr_decode_data(sr, "%AV", sr, &path, vdb) != 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_ERROR);
- }
-
- if (vdb->len != 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_ERROR);
- }
-
- (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0, VAR_BCC, 5, 0);
-
- /* begin search */
- if (smb_rdir_open(sr, path, sattr) != 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_ERROR);
- }
-
- pc = kmem_zalloc(sizeof (*pc), KM_SLEEP);
- pc->dc_cookie = 0;
- count = 0;
- index = 0;
- node = (struct smb_node *)0;
- rc = 0;
-
- if (maxcount > SMB_MAX_SEARCH)
- maxcount = SMB_MAX_SEARCH;
-
- while (count < maxcount) {
- if ((rc = smb_rdir_next(sr, &node, pc)) != 0)
- break;
-
- (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c",
- resume_char,
- pc->dc_name83, pc->dc_name83+9,
- index, sr->smb_sid, client_key,
- pc->dc_dattr & 0xff,
- smb_gmt2local(sr, pc->dc_attr.sa_vattr.va_mtime.tv_sec),
- (int32_t)smb_node_get_size(node, &pc->dc_attr),
- (*pc->dc_shortname) ? pc->dc_shortname : pc->dc_name);
-
- smb_node_release(node);
- node = (struct smb_node *)0;
- count++;
- index++;
- }
- kmem_free(pc, sizeof (*pc));
-
- smb_rdir_close(sr);
-
- if ((rc != 0) && (rc != ENOENT)) {
- /* returned error by smb_rdir_next() */
- kmem_free(vdb, sizeof (struct vardata_block));
- smbsr_errno(sr, rc);
- return (SDRC_ERROR);
- }
-
- if (count == 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
- ERRDOS, ERROR_NO_MORE_FILES);
- return (SDRC_ERROR);
- }
-
- rc = (MBC_LENGTH(&sr->reply) - sr->cur_reply_offset) - 8;
- if (smb_mbc_poke(&sr->reply, sr->cur_reply_offset,
- "bwwbw", 1, count, rc+3, 5, rc) < 0) {
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_ERROR);
- }
-
- kmem_free(vdb, sizeof (struct vardata_block));
- return (SDRC_SUCCESS);
-}
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c Sun Feb 01 19:44:54 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.
*/
@@ -236,10 +236,10 @@
*ret_snode = smb_node_lookup(sr, &sr->arg.open, cr, vp,
name, dir_snode, NULL, ret_attr);
- if (*ret_snode == NULL) {
- VN_RELE(vp);
+ if (*ret_snode == NULL)
rc = ENOMEM;
- }
+
+ VN_RELE(vp);
}
} else {
/*
@@ -271,9 +271,10 @@
rc = smb_fsop_sdwrite(sr, kcred, *ret_snode,
fs_sd, 1);
} else {
- VN_RELE(vp);
rc = ENOMEM;
}
+
+ VN_RELE(vp);
}
if (rc != 0) {
@@ -447,10 +448,10 @@
vp, sname, ret_attr);
smb_node_release(fnode);
+ VN_RELE(xattrdirvp);
+ VN_RELE(vp);
if (*ret_snode == NULL) {
- VN_RELE(xattrdirvp);
- VN_RELE(vp);
kmem_free(fname, MAXNAMELEN);
kmem_free(sname, MAXNAMELEN);
return (ENOMEM);
@@ -498,10 +499,10 @@
*ret_snode = smb_node_lookup(sr, op, cr, vp,
name, dir_snode, NULL, ret_attr);
- if (*ret_snode == NULL) {
- VN_RELE(vp);
+ if (*ret_snode == NULL)
rc = ENOMEM;
- }
+
+ VN_RELE(vp);
}
}
@@ -628,10 +629,10 @@
*ret_snode = smb_node_lookup(sr, op, cr, vp, name,
dir_snode, NULL, ret_attr);
- if (*ret_snode == NULL) {
- VN_RELE(vp);
+ if (*ret_snode == NULL)
rc = ENOMEM;
- }
+
+ VN_RELE(vp);
}
}
@@ -785,15 +786,16 @@
* This function removes a file's streams without removing the
* file itself.
*
- * It is assumed that snode is not a link.
+ * It is assumed that fnode is not a link.
*/
int
smb_fsop_remove_streams(smb_request_t *sr, cred_t *cr, smb_node_t *fnode)
{
- struct fs_stream_info stream_info;
- uint32_t cookie = 0;
- int flags = 0;
- int rc;
+ int rc, flags = 0;
+ uint16_t odid;
+ smb_odir_t *od;
+ smb_odirent_t *odirent;
+ boolean_t eos;
ASSERT(sr);
ASSERT(cr);
@@ -810,16 +812,24 @@
if (SMB_TREE_IS_CASEINSENSITIVE(sr))
flags = SMB_IGNORE_CASE;
- for (;;) {
- rc = smb_vop_stream_readdir(fnode->vp, &cookie, &stream_info,
- NULL, NULL, flags, cr);
+ /* TBD - error codes */
+ if ((odid = smb_odir_openat(sr, fnode)) == 0)
+ return (ENOENT);
+ if ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)
+ return (ENOENT);
- if ((rc != 0) || (cookie == SMB_EOF))
+ odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
+ for (;;) {
+ rc = smb_odir_read(sr, od, odirent, &eos);
+ if ((rc != 0) || (eos))
break;
+ (void) smb_vop_remove(od->d_dnode->vp, odirent->od_name,
+ flags, cr);
+ }
+ kmem_free(odirent, sizeof (smb_odirent_t));
- (void) smb_vop_stream_remove(fnode->vp, stream_info.name, flags,
- cr);
- }
+ smb_odir_release(od);
+ smb_odir_close(od);
return (rc);
}
@@ -971,188 +981,6 @@
}
/*
- * smb_fsop_readdir
- *
- * All SMB functions should use this smb_fsop_readdir wrapper to ensure that
- * the smb_vop_readdir is performed with the appropriate credentials.
- * Please document any direct call to smb_vop_readdir to explain the reason
- * for avoiding this wrapper.
- *
- * It is assumed that a reference exists on snode coming into this routine.
- */
-int
-smb_fsop_readdir(
- smb_request_t *sr,
- cred_t *cr,
- smb_node_t *dir_snode,
- uint32_t *cookie,
- char *name,
- int *namelen,
- ino64_t *fileid,
- struct fs_stream_info *stream_info,
- smb_node_t **ret_snode,
- smb_attr_t *ret_attr)
-{
- smb_node_t *ret_snodep;
- smb_node_t *fnode;
- smb_attr_t tmp_attr;
- vnode_t *xattrdirvp;
- vnode_t *fvp;
- vnode_t *vp = NULL;
- char *od_name;
- int rc;
- int flags = 0;
-
- ASSERT(cr);
- ASSERT(dir_snode);
- ASSERT(dir_snode->n_magic == SMB_NODE_MAGIC);
- ASSERT(dir_snode->n_state != SMB_NODE_STATE_DESTROYING);
-
- if (SMB_TREE_CONTAINS_NODE(sr, dir_snode) == 0)
- return (EACCES);
-
- if (*cookie == SMB_EOF) {
- *namelen = 0;
- return (0);
- }
-
- if (SMB_TREE_IS_CASEINSENSITIVE(sr))
- flags = SMB_IGNORE_CASE;
-
- od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
-
- if (stream_info) {
- rc = smb_vop_lookup(dir_snode->vp, name, &fvp, od_name,
- SMB_FOLLOW_LINKS, sr->tid_tree->t_snode->vp, cr);
-
- if (rc != 0) {
- kmem_free(od_name, MAXNAMELEN);
- return (rc);
- }
-
- fnode = smb_node_lookup(sr, NULL, cr, fvp, od_name, dir_snode,
- NULL, ret_attr);
-
- kmem_free(od_name, MAXNAMELEN);
-
- if (fnode == NULL) {
- VN_RELE(fvp);
- return (ENOMEM);
- }
-
- /*
- * XXX
- * Need to find out what permission(s) NTFS requires for getting
- * a file's streams list.
- *
- * Might have to use kcred.
- */
- rc = smb_vop_stream_readdir(fvp, cookie, stream_info, &vp,
- &xattrdirvp, flags, cr);
-
- if ((rc != 0) || (*cookie == SMB_EOF)) {
- smb_node_release(fnode);
- return (rc);
- }
-
- ret_snodep = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp,
- vp, stream_info->name, &tmp_attr);
-
- smb_node_release(fnode);
-
- if (ret_snodep == NULL) {
- VN_RELE(xattrdirvp);
- VN_RELE(vp);
- return (ENOMEM);
- }
-
- stream_info->size = tmp_attr.sa_vattr.va_size;
-
- if (ret_attr)
- *ret_attr = tmp_attr;
-
- if (ret_snode)
- *ret_snode = ret_snodep;
- else
- smb_node_release(ret_snodep);
-
- } else {
- rc = smb_vop_readdir(dir_snode->vp, cookie, name, namelen,
- fileid, &vp, od_name, flags, cr);
-
- if (rc != 0) {
- kmem_free(od_name, MAXNAMELEN);
- return (rc);
- }
-
- if (*namelen) {
- ASSERT(vp);
- if (ret_attr || ret_snode) {
- ret_snodep = smb_node_lookup(sr, NULL, cr, vp,
- od_name, dir_snode, NULL, &tmp_attr);
-
- if (ret_snodep == NULL) {
- kmem_free(od_name, MAXNAMELEN);
- VN_RELE(vp);
- return (ENOMEM);
- }
-
- if (ret_attr)
- *ret_attr = tmp_attr;
-
- if (ret_snode)
- *ret_snode = ret_snodep;
- else
- smb_node_release(ret_snodep);
- }
- }
-
- kmem_free(od_name, MAXNAMELEN);
- }
-
- return (rc);
-}
-
-/*
- * smb_fsop_getdents
- *
- * All SMB functions should use this smb_vop_getdents wrapper to ensure that
- * the smb_vop_getdents is performed with the appropriate credentials.
- * Please document any direct call to smb_vop_getdents to explain the reason
- * for avoiding this wrapper.
- *
- * It is assumed that a reference exists on snode coming into this routine.
- */
-/*ARGSUSED*/
-int
-smb_fsop_getdents(
- struct smb_request *sr,
- cred_t *cr,
- smb_node_t *dir_snode,
- uint32_t *cookie,
- uint64_t *verifierp,
- int32_t *maxcnt,
- char *args,
- char *pattern)
-{
- int flags = 0;
-
- ASSERT(cr);
- ASSERT(dir_snode);
- ASSERT(dir_snode->n_magic == SMB_NODE_MAGIC);
- ASSERT(dir_snode->n_state != SMB_NODE_STATE_DESTROYING);
-
- if (SMB_TREE_CONTAINS_NODE(sr, dir_snode) == 0)
- return (EACCES);
-
- if (SMB_TREE_IS_CASEINSENSITIVE(sr))
- flags = SMB_IGNORE_CASE;
-
- return (smb_vop_getdents(dir_snode, cookie, 0, maxcnt, args, pattern,
- flags, sr, cr));
-}
-
-/*
* smb_fsop_rename
*
* All SMB functions should use this smb_vop_rename wrapper to ensure that
@@ -1229,17 +1057,14 @@
from_dir_snode, NULL, &tmp_attr);
if (from_snode == NULL) {
- VN_RELE(from_vp);
- return (ENOMEM);
+ rc = ENOMEM;
+ } else {
+ (void) smb_node_rename(from_dir_snode, from_snode,
+ to_dir_snode, to_name);
+ smb_node_release(from_snode);
}
-
- (void) smb_node_rename(from_dir_snode, from_snode, to_dir_snode,
- to_name);
-
- smb_node_release(from_snode);
- } else {
- VN_RELE(from_vp);
}
+ VN_RELE(from_vp);
/* XXX: unlock */
@@ -1749,10 +1574,10 @@
kmem_free(od_name, MAXNAMELEN);
smb_node_release(fnode);
+ VN_RELE(xattrdirvp);
+ VN_RELE(vp);
if (*ret_snode == NULL) {
- VN_RELE(xattrdirvp);
- VN_RELE(vp);
kmem_free(fname, MAXNAMELEN);
kmem_free(sname, MAXNAMELEN);
return (ENOMEM);
@@ -1794,7 +1619,7 @@
* taken if an error is returned.
*
* Note: The returned ret_snode may be in a child mount. This is ok for
- * readdir and getdents.
+ * readdir.
*
* ret_shortname and ret_name83 must each point to buffers of at least
* SMB_SHORTNAMELEN bytes.
@@ -1927,11 +1752,10 @@
*ret_snode = smb_node_lookup(sr, NULL, cr, vp,
lnk_target_node->od_name, lnk_dnode, NULL,
ret_attr);
+ VN_RELE(vp);
- if (*ret_snode == NULL) {
- VN_RELE(vp);
+ if (*ret_snode == NULL)
rc = ENOMEM;
- }
smb_node_release(lnk_target_node);
}
@@ -1948,81 +1772,16 @@
*ret_snode = smb_node_lookup(sr, NULL, cr, vp, od_name,
dir_snode, NULL, ret_attr);
+ VN_RELE(vp);
- if (*ret_snode == NULL) {
- VN_RELE(vp);
+ if (*ret_snode == NULL)
rc = ENOMEM;
- }
}
kmem_free(od_name, MAXNAMELEN);
return (rc);
}
-/*
- * smb_fsop_stream_readdir()
- *
- * ret_snode and ret_attr are optional parameters (i.e. NULL may be passed in)
- *
- * This routine will return only NTFS streams. If an NTFS stream is not
- * found at the offset specified, the directory will be read until an NTFS
- * stream is found or until EOF.
- *
- * Note: Sanity checks done in caller
- * (smb_fsop_readdir(), smb_fsop_remove_streams())
- */
-
-int
-smb_fsop_stream_readdir(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
- uint32_t *cookiep, struct fs_stream_info *stream_info,
- smb_node_t **ret_snode, smb_attr_t *ret_attr)
-{
- smb_node_t *ret_snodep = NULL;
- smb_attr_t tmp_attr;
- vnode_t *xattrdirvp;
- vnode_t *vp;
- int rc = 0;
- int flags = 0;
-
- /*
- * XXX NTFS permission requirements if any?
- */
- ASSERT(cr);
- ASSERT(fnode);
- ASSERT(fnode->n_magic == SMB_NODE_MAGIC);
- ASSERT(fnode->n_state != SMB_NODE_STATE_DESTROYING);
-
- if (SMB_TREE_IS_CASEINSENSITIVE(sr))
- flags = SMB_IGNORE_CASE;
-
- rc = smb_vop_stream_readdir(fnode->vp, cookiep, stream_info, &vp,
- &xattrdirvp, flags, cr);
-
- if ((rc != 0) || *cookiep == SMB_EOF)
- return (rc);
-
- ret_snodep = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp, vp,
- stream_info->name, &tmp_attr);
-
- if (ret_snodep == NULL) {
- VN_RELE(xattrdirvp);
- VN_RELE(vp);
- return (ENOMEM);
- }
-
- stream_info->size = tmp_attr.sa_vattr.va_size;
-
- if (ret_attr)
- *ret_attr = tmp_attr;
-
- if (ret_snode)
- *ret_snode = ret_snodep;
- else
- smb_node_release(ret_snodep);
-
- return (rc);
-}
-
int /*ARGSUSED*/
smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode)
{
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c Sun Feb 01 19:44:54 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.
*/
@@ -65,7 +65,7 @@
uint32_t
smb_kshare_getinfo(door_handle_t dhdl, char *share_name, smb_share_t *si,
- uint32_t ipaddr)
+ smb_inaddr_t *ipaddr)
{
door_arg_t arg;
char *buf;
@@ -80,7 +80,7 @@
enc_ctx = smb_dr_encode_start(buf, SMB_SHARE_DSIZE);
smb_dr_put_uint32(enc_ctx, opcode);
smb_dr_put_string(enc_ctx, share_name);
- smb_dr_put_uint32(enc_ctx, ipaddr);
+ smb_dr_put_buf(enc_ctx, (uchar_t *)ipaddr, sizeof (smb_inaddr_t));
if (smb_dr_encode_finish(enc_ctx, &used) != 0) {
kmem_free(buf, SMB_SHARE_DSIZE);
--- a/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c Sun Feb 01 19:44:54 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.
*/
@@ -52,11 +52,12 @@
* there is a match.
*/
int
-smb_match_name(ino64_t fileid, char *name, char *shortname,
- char *name83, char *pattern, boolean_t ignore_case)
+smb_match_name(ino64_t fileid, char *name, char *pattern, boolean_t ignore_case)
{
int rc = 0;
int force;
+ char name83[SMB_SHORTNAMELEN];
+ char shortname[SMB_SHORTNAMELEN];
/* Leading or trailing dots are disallowed */
if (smb_is_reserved_dos_name(name))
@@ -670,19 +671,17 @@
int
smb_unmangle_name(struct smb_request *sr, cred_t *cred, smb_node_t *dir_node,
char *name, char *real_name, int realname_size, char *shortname,
- char *name83, int od)
+ char *name83, int ondisk)
{
int err;
- int len;
- int force = 0;
- ino64_t inode;
- uint32_t cookie;
struct smb_node *snode = NULL;
smb_attr_t ret_attr;
- char *dot_pos = NULL;
- char *readdir_name;
- char *shortp;
char namebuf[SMB_SHORTNAMELEN];
+ char *path;
+ uint16_t odid;
+ smb_odir_t *od;
+ smb_odirent_t *odirent;
+ boolean_t eos;
if (dir_node == NULL || name == NULL || real_name == NULL ||
realname_size == 0)
@@ -692,7 +691,7 @@
snode = NULL;
if (smb_maybe_mangled_name(name) == 0) {
- if (od == 0) {
+ if (ondisk == 0) {
(void) strlcpy(real_name, name, realname_size);
return (0);
}
@@ -713,65 +712,42 @@
if (name83 == 0)
name83 = namebuf;
- cookie = 0;
-
- readdir_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
-
- snode = NULL;
- while (cookie != 0x7FFFFFFF) {
+ /* determine the pathname and open an smb_odir_t */
+ path = kmem_alloc(MAXNAMELEN, KM_SLEEP);
+ if ((err = vnodetopath(sr->tid_tree->t_snode->vp, dir_node->vp, path,
+ MAXNAMELEN, kcred)) != 0)
+ return (err);
- len = realname_size - 1;
+ if ((strlcat(path, "/*", MAXNAMELEN) >= MAXNAMELEN) ||
+ ((odid = smb_odir_open(sr, path, SMB_SEARCH_ATTRIBUTES)) == 0) ||
+ ((od = smb_tree_lookup_odir(sr->tid_tree, odid)) == NULL)) {
+ err = ENOENT;
+ }
+ kmem_free(path, MAXNAMELEN);
+ if (err != 0)
+ return (err);
- err = smb_fsop_readdir(sr, cred, dir_node, &cookie,
- readdir_name, &len, &inode, NULL, &snode, &ret_attr);
-
- if (err || (cookie == 0x7FFFFFFF))
+ odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
+ for (;;) {
+ err = smb_odir_read(sr, od, odirent, &eos);
+ if ((err != 0) || (eos))
break;
- readdir_name[len] = 0;
-
- /*
- * smb_fsop_readdir() may return a mangled name if the
- * name has a case collision.
- *
- * If readdir_name is not a mangled name, we mangle
- * readdir_name to see if it will match the name the
- * client passed in.
- *
- * If smb_needs_mangle() does not succeed, we try again
- * using the force flag. It is possible that the client
- * is using a mangled name that resulted from a prior
- * case collision which no longer exists in the directory.
- * smb_needs_mangle(), with the force flag, will produce
- * a mangled name regardless of whether the name passed in
- * meets standard DOS criteria for name mangling.
- */
+ (void) smb_mangle_name(odirent->od_ino, odirent->od_name,
+ shortname, name83, 1);
- if (smb_maybe_mangled_name(readdir_name)) {
- shortp = readdir_name;
- } else {
- if (smb_needs_mangle(readdir_name, &dot_pos) == 0)
- force = 1;
- (void) smb_mangle_name(inode, readdir_name, shortname,
- name83, force);
- shortp = shortname;
- }
-
- if (utf8_strcasecmp(name, shortp) == 0) {
- kmem_free(readdir_name, MAXNAMELEN);
- (void) strlcpy(real_name, snode->od_name,
+ if (utf8_strcasecmp(name, shortname) == 0) {
+ (void) strlcpy(real_name, odirent->od_name,
realname_size);
-
- smb_node_release(snode);
-
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ smb_odir_release(od);
+ smb_odir_close(od);
return (0);
- } else {
- smb_node_release(snode);
- snode = NULL;
}
}
- kmem_free(readdir_name, MAXNAMELEN);
-
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ smb_odir_release(od);
+ smb_odir_close(od);
return (ENOENT);
}
--- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c Sun Feb 01 19:44:54 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.
*/
@@ -197,7 +197,6 @@
#include <smbsrv/smbinfo.h>
#include <smbsrv/smb_i18n.h>
-
/*
* Maximum buffer size for DOS: chosen to be the same as NT.
* Do not change this value, DOS is very sensitive to it.
@@ -255,7 +254,7 @@
int rc;
unsigned short max_mpx_count;
int16_t tz_correction;
- char ipaddr_buf[INET_ADDRSTRLEN];
+ char ipaddr_buf[INET6_ADDRSTRLEN];
char *tmpbuf;
int buflen;
smb_msgbuf_t mb;
@@ -394,9 +393,8 @@
sr->session->secmode = secmode;
}
-
- (void) inet_ntop(AF_INET, (char *)&sr->session->ipaddr,
- ipaddr_buf, sizeof (ipaddr_buf));
+ (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
+ SMB_IPSTRLEN(sr->session->ipaddr.a_family));
max_mpx_count = sr->sr_cfg->skc_maxworkers;
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c Sun Feb 01 19:44:54 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.
*/
@@ -171,10 +171,9 @@
*
* smb_node_lookup() is called upon successful lookup, mkdir, and create
* (for both non-streams and streams). In each of these cases, a held vnode is
- * passed into this routine. If an smb_node already exists for this vnode,
- * the vp is released. Otherwise, a new smb_node will be created and the
- * reference will be held until the refcnt on the node goes to 0 (see
- * smb_node_release()).
+ * passed into this routine. If a new smb_node is created it will take its
+ * own hold on the vnode. The caller's hold therefore still belongs to, and
+ * should be released by, the caller.
*
* A reference is taken on the smb_node whether found in the hash table
* or newly created.
@@ -272,7 +271,6 @@
smb_audit_node(node);
smb_rwx_xexit(&node->n_lock);
smb_llist_exit(node_hdr);
- VN_RELE(vp);
return (node);
case SMB_NODE_STATE_DESTROYING:
@@ -309,6 +307,7 @@
node->n_hash_bucket = node_hdr;
node->n_sr = sr;
node->vp = vp;
+ VN_HOLD(node->vp);
node->n_hashkey = hashkey;
node->n_refcnt = 1;
node->attr = *attr;
@@ -381,15 +380,6 @@
snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
fnode, ret_attr);
- /*
- * The following VN_HOLD is necessary because the caller will VN_RELE
- * xattrdirvp in the case of an error. (xattrdir_node has the original
- * hold on the vnode, which the smb_node_release() call below will
- * release.)
- */
- if (snode == NULL) {
- VN_HOLD(xattrdirvp);
- }
(void) smb_node_release(xattrdir_node);
return (snode);
}
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c Sun Feb 01 19:44:54 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"
-
/*
* SMB: nt_cancel
*
@@ -71,7 +69,6 @@
while (req) {
ASSERT(req->sr_magic == SMB_REQ_MAGIC);
if ((req != sr) &&
- (req->smb_sid == sr->smb_sid) &&
(req->smb_uid == sr->smb_uid) &&
(req->smb_pid == sr->smb_pid) &&
(req->smb_tid == sr->smb_tid) &&
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c Sun Feb 01 19:44:54 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 "@(#)smb_nt_transact_notify_change.c 1.6 08/08/07 SMI"
-
/*
* File Change Notification (FCN)
*/
@@ -495,7 +493,6 @@
ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
tmp = smb_slist_next(&smb_ncr_list, sr);
if ((sr->session == zsr->session) &&
- (sr->smb_sid == zsr->smb_sid) &&
(sr->smb_uid == zsr->smb_uid) &&
(sr->smb_pid == zsr->smb_pid) &&
(sr->smb_tid == zsr->smb_tid) &&
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c Sun Feb 01 19:44:54 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"
-
/*
* General Structures Layout
* -------------------------
@@ -70,64 +68,45 @@
* Odir State Machine
* ------------------
*
- * +-------------------------+ T0
- * | SMB_ODIR_STATE_OPEN |<----------- Creation/Allocation
+ * +-------------------------+
+ * | SMB_ODIR_STATE_OPEN |<----------- open / creation
* +-------------------------+
* |
- * | T1
+ * | close
+ * |
+ * v
+ * +-------------------------+
+ * | SMB_ODIR_STATE_CLOSING |
+ * +-------------------------+
+ * |
+ * | last release
* |
* v
* +-------------------------+
- * | SMB_ODIR_STATE_CLOSING |
- * +-------------------------+
- * |
- * | T2
- * |
- * v
- * +-------------------------+ T3
- * | SMB_ODIR_STATE_CLOSED |----------> Deletion/Free
+ * | SMB_ODIR_STATE_CLOSED |----------> deletion
* +-------------------------+
*
+ *
* SMB_ODIR_STATE_OPEN
- *
- * While in this state:
- * - The odir is queued in the list of odirs of its tree.
- * - References will be given out if the odir is looked up.
+ * - the odir exists in the list of odirs of its tree.
+ * - references will be given out if the odir is looked up
+ * - if a close is received the odir will transition to
+ * SMB_ODIR_STATE_CLOSING.
*
* SMB_ODIR_STATE_CLOSING
- *
- * While in this state:
- * - The odir is queued in the list of odirs of its tree.
- * - References will not be given out if the odir is looked up.
- * - The odir is closed.
- * - The resources associated with the odir remain.
+ * - the odir exists in the list of odirs of its tree.
+ * - references will NOT be given out if the odir is looked up.
+ * - when the last reference is released (refcnt == 0) the
+ * odir will transition to SMB_ODIR_STATE_CLOSED.
*
* SMB_ODIR_STATE_CLOSED
- *
- * While in this state:
- * - The odir is queued in the list of odirs of its tree.
- * - References will not be given out if the odir is looked up.
- * - The resources associated with the odir remain.
- *
- * Transition T0
- *
- * This transition occurs in smb_odir_open(). A new odir is created and
- * added to the list of odirs of a tree.
- *
- * Transition T1
- *
- * This transition occurs in smb_odir_close().
- *
- * Transition T2
- *
- * This transition occurs in smb_odir_release(). The resources associated
- * with the odir are freed as well as the odir structure. For the
- * transition to occur, the odir must be in the SMB_ODIR_STATE_CLOSED
- * state and the reference count be zero.
+ * - the odir exists in the list of odirs of its tree.
+ * - there are no users of the odir (refcnt == 0)
+ * - references will NOT be given out if the odir is looked up.
+ * - the odir is being removed from the tree's list and deleted.
*
* Comments
* --------
- *
* The state machine of the odir structures is controlled by 3 elements:
* - The list of odirs of the tree it belongs to.
* - The mutex embedded in the structure itself.
@@ -139,319 +118,1008 @@
* To insert the odir into the list of odirs of the tree and to remove
* the odir from it, the lock must be entered in RW_WRITER mode.
*
- * Rules of access to a odir structure:
+ * In order to avoid deadlocks, when both (mutex and lock of the odir
+ * list) have to be entered, the lock must be entered first.
+ *
+ *
+ * Odir Interface
+ * ---------------
+ * odid = smb_odir_open(pathname)
+ * Create an odir representing the directory specified in pathname and
+ * add it into the tree's list of odirs.
+ * Return an identifier (odid) uniquely identifying the created odir.
*
- * 1) In order to avoid deadlocks, when both (mutex and lock of the odir
- * list) have to be entered, the lock must be entered first.
+ * smb_odir_openat(smb_node_t *unode)
+ * Create an odir representing the extended attribute directory
+ * associated with the file (or directory) represented by unode
+ * and add it into the tree's list of odirs.
+ * Return an identifier (odid) uniquely identifying the created odir.
+ *
+ * smb_odir_t *odir = smb_tree_lookup_odir(odid)
+ * Find the odir corresponding to the specified odid in the tree's
+ * list of odirs.
+ *
+ * smb_odir_read(..., smb_odirent_t *odirent)
+ * Find the next directory entry in the odir and return it in odirent.
*
- * 2) All actions applied to an odir require a reference count.
+ * smb_odir_read_fileinfo(..., smb_fileinfo_t *)
+ * Find the next directory entry in the odir. Return the details of
+ * the directory entry in smb_fileinfo_t. (See odir internals below)
+ *
+ * smb_odir_read_stream_info(..., smb_streaminfo_t *)
+ * Find the next named stream entry in the odir. Return the details of
+ * the named stream in smb_streaminfo_t.
+ *
+ * smb_odir_release(smb_odir_t *odir)
+ * Release the hold on the odir, obtained by lookup.
+ *
+ * smb_odir_close(smb_odir_t *odir)
+ * Close the odir and remove it from the tree's list of odirs.
*
- * 3) There are 2 ways of getting a reference count. One is when the odir
- * is opened. The other when the odir is looked up. This translates
- * into 2 functions: smb_odir_open() and smb_odir_lookup_by_fid().
+ *
+ * Odir Internals
+ * --------------
+ * The odir object represent an open directory search. Each read operation
+ * provides the caller with a structure containing information pertaining
+ * to the next directory entry that matches the search criteria, namely
+ * the filename or match pattern and, in the case of smb_odir_read_fileinfo(),
+ * the search attributes.
+ *
+ * The odir maintains a buffer (d_buf) of directory entries read from
+ * the filesystem via a vop_readdir. The buffer is populated when a read
+ * request (smb_odir_next_odirent) finds that the buffer is empty or that
+ * the end of the buffer has been reached, and also when a new client request
+ * (find next) begins.
*
- * It should be noted that the reference count of an odir registers the
- * number of references to the odir in other structures (such as an smb
- * request). The reference count is not incremented in these 2 instances:
+ * The data in d_buf (that which is returned from the file system) can
+ * be in one of two formats. If the file system supports extended directory
+ * entries we request that the data be returned as edirent_t structures. If
+ * it does not the data will be returned as dirent64_t structures. For
+ * convenience, when the next directory entry is read from d_buf by
+ * smb_odir_next_odirent it is translated into an smb_odirent_t.
+ *
+ * smb_odir_read_fileinfo
+ * The processing required to obtain the information to populate the caller's
+ * smb_fileinfo_t differs depending upon whether the directory search is for a
+ * single specified filename or for multiple files matching a search pattern.
+ * Thus smb_odir_read_fileinfo uses two static functions:
+ * smb_odir_single_fileinfo - obtains the smb_fileinfo_t info for the single
+ * filename as specified in smb_odir_open request.
+ * smb_odir_wildcard_fileinfo - obtains the smb_fileinfo_t info for the filename
+ * returned from the smb_odir_next_odirent. This is called in a loop until
+ * an entry matching the search criteria is found or no more entries exist.
+ *
+ * If a directory entry is a VLNK, the name returned in the smb_fileinfo_t
+ * is the name of the directory entry but the attributes are the attribites
+ * of the file that is the target of the link. If the link target cannot
+ * be found the attributes returned are the attributes of the link itself.
*
- * 1) The odir is open. An odir is anchored by his state. If there's
- * no activity involving an odir currently open, the reference count
- * of that odir is zero.
+ * smb_odir_read_stream_info
+ * In order for an odir to provide information about stream files it
+ * must be opened with smb_odir_openat(). smb_odir_read_streaminfo() can
+ * then be used to obtain the name and size of named stream files.
*
- * 2) The odir is queued in the list of odirs of its tree. The fact of
- * being queued in that list is NOT registered by incrementing the
- * reference count.
+ * Resuming a Search
+ * -----------------
+ * A directory search often consists of multiple client requests: an initial
+ * find_first request followed by zero or more find_next requests and a
+ * find_close request.
+ * The find_first request will open and lookup the odir, read its desired
+ * number of entries from the odir, then release the odir and return.
+ * A find_next request will lookup the odir and read its desired number of
+ * entries from the odir, then release the odir and return.
+ * At the end of the search the find_close request will close the odir.
+ *
+ * In order to be able to resume a directory search (find_next) the odir
+ * provides the capability for the caller to save one or more resume points
+ * (cookies) at the end of a request, and to specify which resume point
+ * (cookie) to restart from at the beginning of the next search.
+ * smb_odir_save_cookie(..., cookie)
+ * smb_odir_resume_at(smb_odir_resume_t *resume)
+ * A search can be resumed at a specified resume point (cookie), the resume
+ * point (cookie) stored at a specified index in the d_cookies array, or
+ * a specified filename. The latter (specified filename) is not yet supported.
+ *
+ * See smb_search, smb_find, smb_find_unique, and smb_trans2_find for details
*/
+
#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
+#include <sys/extdirent.h>
-/* Static functions defined further down this file. */
-static void smb_odir_delete(smb_odir_t *of);
-static smb_odir_t *smb_odir_close_and_next(smb_odir_t *od);
+/* static functions */
+static smb_odir_t *smb_odir_create(smb_request_t *, smb_node_t *,
+ char *, uint16_t);
+static void smb_odir_delete(smb_odir_t *);
+static int smb_odir_single_fileinfo(smb_request_t *, smb_odir_t *,
+ smb_fileinfo_t *);
+static int smb_odir_wildcard_fileinfo(smb_request_t *, smb_odir_t *,
+ smb_odirent_t *, smb_fileinfo_t *);
+static int smb_odir_next_odirent(smb_odir_t *, smb_odirent_t *);
+static boolean_t smb_odir_lookup_link(smb_request_t *, smb_odir_t *, char *,
+ smb_node_t **, smb_attr_t *);
-#include <smbsrv/smb_incl.h>
-#include <smbsrv/smb_fsops.h>
/*
* smb_odir_open
+ *
+ * Create an odir representing the directory specified in pathname.
+ *
+ * Returns:
+ * odid - Unique identifier of newly created odir.
+ * 0 - error, error details set in sr.
*/
-smb_odir_t *
-smb_odir_open(
- smb_tree_t *tree,
- smb_node_t *node,
- char *pattern,
- uint16_t pid,
- unsigned short sattr)
+uint16_t
+smb_odir_open(smb_request_t *sr, char *path, uint16_t sattr)
{
- smb_odir_t *dir;
+ int rc;
+ smb_tree_t *tree;
+ smb_node_t *dnode;
+ char pattern[MAXNAMELEN];
+ smb_odir_t *od;
- ASSERT(tree);
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
- ASSERT(node);
- ASSERT(node->n_magic == SMB_NODE_MAGIC);
- ASSERT(pattern);
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(sr->tid_tree);
+ ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC);
- if (strlen(pattern) >= sizeof (dir->d_pattern)) {
- return (NULL);
+ tree = sr->tid_tree;
+
+ rc = smb_pathname_reduce(sr, sr->user_cr, path,
+ tree->t_snode, tree->t_snode, &dnode, pattern);
+ if (rc != 0) {
+ smbsr_errno(sr, rc);
+ return (0);
}
- dir = kmem_cache_alloc(tree->t_server->si_cache_odir, KM_SLEEP);
- bzero(dir, sizeof (smb_odir_t));
- dir->d_refcnt = 1;
- dir->d_session = tree->t_session;
- dir->d_user = tree->t_user;
- dir->d_tree = tree;
- (void) strlcpy(dir->d_pattern, pattern, sizeof (dir->d_pattern));
- dir->d_wildcards = smb_convert_unicode_wildcards(pattern);
- dir->d_state = SMB_ODIR_STATE_OPEN;
-
- if (smb_idpool_alloc(&dir->d_tree->t_sid_pool, &dir->d_sid)) {
- kmem_cache_free(tree->t_server->si_cache_odir, dir);
- return (NULL);
+ if (dnode->vp->v_type != VDIR) {
+ smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND,
+ ERRDOS, ERROR_PATH_NOT_FOUND);
+ smb_node_release(dnode);
+ return (0);
}
- mutex_init(&dir->d_mutex, NULL, MUTEX_DEFAULT, NULL);
- dir->d_sattr = sattr;
- dir->d_opened_by_pid = pid;
- dir->d_dir_snode = node;
- dir->d_state = SMB_ODIR_STATE_OPEN;
- dir->d_magic = SMB_ODIR_MAGIC;
- smb_llist_enter(&tree->t_odir_list, RW_WRITER);
- smb_llist_insert_tail(&tree->t_odir_list, dir);
- smb_llist_exit(&tree->t_odir_list);
+ if (smb_fsop_access(sr, sr->user_cr, dnode, FILE_LIST_DIRECTORY) != 0) {
+ smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
+ ERRDOS, ERROR_ACCESS_DENIED);
+ smb_node_release(dnode);
+ return (0);
+ }
- atomic_inc_32(&tree->t_session->s_dir_cnt);
- return (dir);
+ od = smb_odir_create(sr, dnode, pattern, sattr);
+ smb_node_release(dnode);
+ return (od ? od->d_odid : 0);
}
/*
- * smb_odir_close
+ * smb_odir_openat
+ *
+ * Create an odir representing the extended attribute directory
+ * associated with the file (or directory) represented by unode.
+ *
+ * Returns:
+ * odid - Unique identifier of newly created odir.
+ * 0 - error, error details set in sr.
+ */
+uint16_t
+smb_odir_openat(smb_request_t *sr, smb_node_t *unode)
+{
+ int rc;
+ vnode_t *xattr_dvp;
+ smb_odir_t *od;
+ cred_t *cr;
+ char pattern[SMB_STREAM_PREFIX_LEN + 2];
+
+ smb_node_t *xattr_dnode;
+ smb_attr_t tmp_attr;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(unode);
+ ASSERT(unode->n_magic == SMB_NODE_MAGIC);
+
+ if (SMB_TREE_CONTAINS_NODE(sr, unode) == 0) {
+ smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
+ ERRDOS, ERROR_ACCESS_DENIED);
+ return (0);
+ }
+ cr = sr->user_cr;
+
+ /* find the xattrdir vnode */
+ rc = smb_vop_lookup_xattrdir(unode->vp, &xattr_dvp, LOOKUP_XATTR, cr);
+ if (rc != 0) {
+ smbsr_errno(sr, rc);
+ return (0);
+ }
+
+ /* lookup the xattrdir's smb_node */
+ xattr_dnode = smb_node_lookup(sr, NULL, cr, xattr_dvp, XATTR_DIR,
+ unode, NULL, &tmp_attr);
+ VN_RELE(xattr_dvp);
+ if (xattr_dnode == NULL) {
+ smbsr_error(sr, NT_STATUS_NO_MEMORY,
+ ERRDOS, ERROR_NOT_ENOUGH_MEMORY);
+ return (0);
+ }
+
+ (void) snprintf(pattern, sizeof (pattern), "%s*", SMB_STREAM_PREFIX);
+ od = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES);
+ smb_node_release(xattr_dnode);
+ if (od == NULL)
+ return (0);
+
+ od->d_xat = B_TRUE;
+ return (od->d_odid);
+}
+
+/*
+ * smb_odir_hold
+ */
+boolean_t
+smb_odir_hold(smb_odir_t *od)
+{
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+
+ mutex_enter(&od->d_mutex);
+ if (od->d_state != SMB_ODIR_STATE_OPEN) {
+ mutex_exit(&od->d_mutex);
+ return (B_FALSE);
+ }
+
+ od->d_refcnt++;
+ mutex_exit(&od->d_mutex);
+ return (B_TRUE);
+}
+
+/*
+ * smb_odir_release
+ *
+ * If the odir is in SMB_ODIR_STATE_CLOSING and this release
+ * results in a refcnt of 0, the odir may be removed from
+ * the tree's list of odirs and deleted. The odir's state is
+ * set to SMB_ODIR_STATE_CLOSED prior to exiting the mutex and
+ * deleting it. This ensure that nobody else can ontain a reference
+ * to it while we are deleting it.
*/
void
-smb_odir_close(
- smb_odir_t *od)
+smb_odir_release(smb_odir_t *od)
{
ASSERT(od);
ASSERT(od->d_magic == SMB_ODIR_MAGIC);
mutex_enter(&od->d_mutex);
ASSERT(od->d_refcnt);
+
switch (od->d_state) {
case SMB_ODIR_STATE_OPEN:
- od->d_state = SMB_ODIR_STATE_CLOSED;
+ od->d_refcnt--;
break;
case SMB_ODIR_STATE_CLOSING:
+ od->d_refcnt--;
+ if (od->d_refcnt == 0) {
+ od->d_state = SMB_ODIR_STATE_CLOSED;
+ mutex_exit(&od->d_mutex);
+ smb_odir_delete(od);
+ return;
+ }
+ break;
case SMB_ODIR_STATE_CLOSED:
break;
default:
ASSERT(0);
break;
}
- mutex_exit(&od->d_mutex);
-}
-/*
- * smb_odir_close_all
- *
- *
- */
-void
-smb_odir_close_all(
- smb_tree_t *tree)
-{
- smb_odir_t *od;
-
- ASSERT(tree);
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
-
- smb_llist_enter(&tree->t_odir_list, RW_READER);
- od = smb_llist_head(&tree->t_odir_list);
- while (od) {
- ASSERT(od->d_magic == SMB_ODIR_MAGIC);
- ASSERT(od->d_tree == tree);
- od = smb_odir_close_and_next(od);
- }
- smb_llist_exit(&tree->t_odir_list);
-}
-
-/*
- * smb_odir_close_all_by_pid
- *
- *
- */
-void
-smb_odir_close_all_by_pid(
- smb_tree_t *tree,
- uint16_t pid)
-{
- smb_odir_t *od;
-
- ASSERT(tree);
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
-
- smb_llist_enter(&tree->t_odir_list, RW_READER);
- od = smb_llist_head(&tree->t_odir_list);
- while (od) {
- ASSERT(od->d_magic == SMB_ODIR_MAGIC);
- ASSERT(od->d_tree == tree);
- if (od->d_opened_by_pid == pid) {
- od = smb_odir_close_and_next(od);
- } else {
- od = smb_llist_next(&tree->t_odir_list, od);
- }
- }
- smb_llist_exit(&tree->t_odir_list);
-}
-
-/*
- * smb_odir_release
- */
-void
-smb_odir_release(
- smb_odir_t *od)
-{
- ASSERT(od);
- ASSERT(od->d_magic == SMB_ODIR_MAGIC);
-
- mutex_enter(&od->d_mutex);
- ASSERT(od->d_refcnt);
- od->d_refcnt--;
- switch (od->d_state) {
- case SMB_ODIR_STATE_CLOSING:
- case SMB_ODIR_STATE_OPEN:
- break;
-
- case SMB_ODIR_STATE_CLOSED:
- if (od->d_refcnt == 0) {
- mutex_exit(&od->d_mutex);
- smb_odir_delete(od);
- return;
- }
- break;
-
- default:
- ASSERT(0);
- break;
- }
mutex_exit(&od->d_mutex);
}
/*
- * smb_odir_lookup_by_sid
+ * smb_odir_close
*/
-smb_odir_t *
-smb_odir_lookup_by_sid(
- smb_tree_t *tree,
- uint16_t sid)
+void
+smb_odir_close(smb_odir_t *od)
{
- smb_llist_t *od_list;
- smb_odir_t *od;
+ ASSERT(od);
+ ASSERT(od->d_refcnt);
- ASSERT(tree);
- ASSERT(tree->t_magic == SMB_TREE_MAGIC);
+ mutex_enter(&od->d_mutex);
+ if (od->d_state != SMB_ODIR_STATE_OPEN) {
+ mutex_exit(&od->d_mutex);
+ return;
+ }
+ od->d_state = SMB_ODIR_STATE_CLOSING;
+ mutex_exit(&od->d_mutex);
- od_list = &tree->t_odir_list;
+ smb_odir_release(od);
+}
- smb_llist_enter(od_list, RW_READER);
- od = smb_llist_head(od_list);
- while (od) {
- ASSERT(od->d_magic == SMB_ODIR_MAGIC);
- ASSERT(od->d_tree == tree);
- if (od->d_sid == sid) {
- mutex_enter(&od->d_mutex);
- if (od->d_state != SMB_ODIR_STATE_OPEN) {
- mutex_exit(&od->d_mutex);
- smb_llist_exit(od_list);
- return (NULL);
- }
- od->d_refcnt++;
- mutex_exit(&od->d_mutex);
+/*
+ * smb_odir_read
+ *
+ * Find the next directory entry matching the search pattern.
+ * No search attribute matching is performed.
+ *
+ * Returns:
+ * 0 - success.
+ * - If a matching entry was found eof will be B_FALSE and
+ * odirent will be populated.
+ * - If there are no matching entries eof will be B_TRUE.
+ * -1 - error, error details set in sr.
+ */
+int
+smb_odir_read(smb_request_t *sr, smb_odir_t *od,
+ smb_odirent_t *odirent, boolean_t *eof)
+{
+ int rc;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(odirent);
+
+ mutex_enter(&od->d_mutex);
+
+ ASSERT(od->d_state == SMB_ODIR_STATE_OPEN);
+ if (od->d_state != SMB_ODIR_STATE_OPEN) {
+ mutex_exit(&od->d_mutex);
+ return (-1);
+ }
+
+ for (;;) {
+ if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
break;
- }
- od = smb_llist_next(od_list, od);
+ if (smb_match_name(odirent->od_ino, odirent->od_name,
+ od->d_pattern, od->d_ignore_case))
+ break;
}
- smb_llist_exit(od_list);
- return (od);
+
+ mutex_exit(&od->d_mutex);
+
+ switch (rc) {
+ case 0:
+ *eof = B_FALSE;
+ return (0);
+ case ENOENT:
+ *eof = B_TRUE;
+ return (0);
+ default:
+ smbsr_errno(sr, rc);
+ return (-1);
+ }
}
-/* *************************** Static Functions ***************************** */
+/*
+ * smb_odir_read_fileinfo
+ *
+ * Find the next directory entry matching the search pattern
+ * and attributes: od->d_pattern and od->d_sattr.
+ *
+ * If the search pattern specifies a single filename call
+ * smb_odir_single_fileinfo to get the file attributes and
+ * populate the caller's smb_fileinfo_t.
+ *
+ * If the search pattern contains wildcards call smb_odir_next_odirent
+ * to get the next directory entry then. Repeat until a matching
+ * filename is found. Call smb_odir_wildcard_fileinfo to get the
+ * file attributes and populate the caller's smb_fileinfo_t.
+ * This is repeated until a file matching the search criteria is found.
+ *
+ * Returns:
+ * 0 - success.
+ * - If a matching entry was found eof will be B_FALSE and
+ * fileinfo will be populated.
+ * - If there are no matching entries eof will be B_TRUE.
+ * -1 - error, error details set in sr.
+ */
+int
+smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
+ smb_fileinfo_t *fileinfo, boolean_t *eof)
+{
+ int rc;
+ smb_odirent_t *odirent;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(fileinfo);
+
+ mutex_enter(&od->d_mutex);
+
+ ASSERT(od->d_state == SMB_ODIR_STATE_OPEN);
+ if (od->d_state != SMB_ODIR_STATE_OPEN) {
+ mutex_exit(&od->d_mutex);
+ return (-1);
+ }
+
+ if (!od->d_wildcards) {
+ if (od->d_eof)
+ rc = ENOENT;
+ else
+ rc = smb_odir_single_fileinfo(sr, od, fileinfo);
+ od->d_eof = B_TRUE;
+ } else {
+ odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
+ for (;;) {
+ bzero(fileinfo, sizeof (smb_fileinfo_t));
+ if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
+ break;
+
+ if (!smb_match_name(odirent->od_ino, odirent->od_name,
+ od->d_pattern, od->d_ignore_case))
+ continue;
+
+ rc = smb_odir_wildcard_fileinfo(sr, od, odirent,
+ fileinfo);
+ if (rc == 0)
+ break;
+ }
+ kmem_free(odirent, sizeof (smb_odirent_t));
+ }
+ mutex_exit(&od->d_mutex);
+
+ switch (rc) {
+ case 0:
+ *eof = B_FALSE;
+ return (0);
+ case ENOENT:
+ *eof = B_TRUE;
+ return (0);
+ default:
+ smbsr_errno(sr, rc);
+ return (-1);
+ }
+}
+
/*
- * smb_odir_close_and_next
+ * smb_odir_read_streaminfo
+ *
+ * Find the next directory entry whose name begins with SMB_STREAM_PREFIX,
+ * and thus represents an NTFS named stream.
+ * No search attribute matching is performed.
*
- * This function closes the directory passed in (if appropriate) and returns the
- * next directory in the list of directories of the tree of the directory passed
- * in. It requires that the list of directories of the tree be entered in
- * RW_READER mode before being called.
+ * Returns:
+ * 0 - success.
+ * - If a matching entry was found eof will be B_FALSE and
+ * sinfo will be populated.
+ * - If there are no matching entries eof will be B_TRUE.
+ * -1 - error, error details set in sr.
*/
-static smb_odir_t *
-smb_odir_close_and_next(
- smb_odir_t *od)
+int
+smb_odir_read_streaminfo(smb_request_t *sr, smb_odir_t *od,
+ smb_streaminfo_t *sinfo, boolean_t *eof)
{
- smb_odir_t *next_od;
- smb_tree_t *tree;
+ int rc;
+ smb_odirent_t *odirent;
+ vnode_t *vp;
+ smb_attr_t attr;
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
ASSERT(od);
ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(sinfo);
+
+ mutex_enter(&od->d_mutex);
+
+ ASSERT(od->d_state == SMB_ODIR_STATE_OPEN);
+ if (od->d_state != SMB_ODIR_STATE_OPEN) {
+ mutex_exit(&od->d_mutex);
+ return (-1);
+ }
+
+ /* Check that odir represents an xattr directory */
+ if (!od->d_xat) {
+ *eof = B_TRUE;
+ mutex_exit(&od->d_mutex);
+ return (0);
+ }
+
+ odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
+
+ for (;;) {
+ bzero(sinfo, sizeof (smb_streaminfo_t));
+ if ((rc = smb_odir_next_odirent(od, odirent)) != 0)
+ break;
+
+ if (strncmp(odirent->od_name, SMB_STREAM_PREFIX,
+ SMB_STREAM_PREFIX_LEN)) {
+ continue;
+ }
+
+ /*
+ * since we only care about the size attribute we don't need to
+ * pass the vp of the unnamed stream file to smb_vop_getattr
+ */
+ rc = smb_vop_lookup(od->d_dnode->vp, odirent->od_name, &vp,
+ NULL, 0, od->d_tree->t_snode->vp, od->d_user->u_cred);
+ if (rc == 0) {
+ rc = smb_vop_getattr(vp, NULL, &attr, 0,
+ od->d_user->u_cred);
+ VN_RELE(vp);
+ }
+
+ if (rc == 0) {
+ (void) strlcpy(sinfo->si_name,
+ odirent->od_name + SMB_STREAM_PREFIX_LEN,
+ sizeof (sinfo->si_name));
+ sinfo->si_size = attr.sa_vattr.va_size;
+ break;
+ }
+ }
+ mutex_exit(&od->d_mutex);
+
+ kmem_free(odirent, sizeof (smb_odirent_t));
+
+ switch (rc) {
+ case 0:
+ *eof = B_FALSE;
+ return (0);
+ case ENOENT:
+ *eof = B_TRUE;
+ return (0);
+ default:
+ smbsr_errno(sr, rc);
+ return (-1);
+ }
+}
+
+/*
+ * smb_odir_save_cookie
+ *
+ * Callers can save up to SMB_MAX_SEARCH cookies in the odir
+ * to be used as resume points for a 'find next' request.
+ */
+void
+smb_odir_save_cookie(smb_odir_t *od, int idx, uint32_t cookie)
+{
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(idx >= 0 && idx < SMB_MAX_SEARCH);
mutex_enter(&od->d_mutex);
- switch (od->d_state) {
- case SMB_ODIR_STATE_OPEN:
- /* The directory is still opened. */
- od->d_refcnt++;
- ASSERT(od->d_refcnt);
- tree = od->d_tree;
- mutex_exit(&od->d_mutex);
- smb_llist_exit(&od->d_tree->t_odir_list);
- smb_odir_close(od);
- smb_odir_release(od);
- smb_llist_enter(&tree->t_odir_list, RW_READER);
- next_od = smb_llist_head(&tree->t_odir_list);
- break;
- case SMB_ODIR_STATE_CLOSING:
- case SMB_ODIR_STATE_CLOSED:
- /*
- * The odir exists but is closed or is in the process
- * of being closed.
- */
- mutex_exit(&od->d_mutex);
- next_od = smb_llist_next(&od->d_tree->t_odir_list, od);
- break;
- default:
- ASSERT(0);
- mutex_exit(&od->d_mutex);
- next_od = smb_llist_next(&od->d_tree->t_odir_list, od);
- break;
+ od->d_cookies[idx] = cookie;
+ mutex_exit(&od->d_mutex);
+}
+
+/*
+ * smb_odir_resume_at
+ *
+ * Searching can be resumed from:
+ * - the cookie saved at a specified index (SMBsearch, SMBfind).
+ * - a specified cookie (SMB_trans2_find)
+ * - a specified filename (SMB_trans2_find) - NOT SUPPORTED.
+ * Defaults to continuing from where the last search ended.
+ *
+ * Continuation from where the last search ended (SMB_trans2_find)
+ * is implemented by saving the last cookie at a specific index (0)
+ * smb_odir_resume_at indicates a new request, so reset od->d_bufptr
+ * and d_eof to force a vop_readdir.
+ */
+void
+smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume)
+{
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(resume);
+
+ mutex_enter(&od->d_mutex);
+
+ switch (resume->or_type) {
+ case SMB_ODIR_RESUME_IDX:
+ ASSERT(resume->or_idx >= 0);
+ ASSERT(resume->or_idx < SMB_MAX_SEARCH);
+
+ if ((resume->or_idx < 0) ||
+ (resume->or_idx >= SMB_MAX_SEARCH)) {
+ resume->or_idx = 0;
+ }
+ od->d_offset = od->d_cookies[resume->or_idx];
+ break;
+ case SMB_ODIR_RESUME_COOKIE:
+ od->d_offset = resume->or_cookie;
+ break;
+ case SMB_ODIR_RESUME_FNAME:
+ default:
+ od->d_offset = od->d_cookies[0];
+ break;
}
- return (next_od);
+
+ /* Force a vop_readdir to refresh d_buf */
+ od->d_bufptr = NULL;
+ od->d_eof = B_FALSE;
+
+ mutex_exit(&od->d_mutex);
+}
+
+
+/* *** static functions *** */
+
+/*
+ * smb_odir_create
+ * Allocate and populate an odir obect and add it to the tree's list.
+ */
+static smb_odir_t *
+smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
+ char *pattern, uint16_t sattr)
+{
+ smb_odir_t *od;
+ smb_tree_t *tree;
+ uint16_t odid;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(sr->tid_tree);
+ ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC);
+ ASSERT(dnode);
+ ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
+
+ tree = sr->tid_tree;
+
+ if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) {
+ smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
+ ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
+ return (NULL);
+ }
+
+ od = kmem_cache_alloc(tree->t_server->si_cache_odir, KM_SLEEP);
+ bzero(od, sizeof (smb_odir_t));
+
+ mutex_init(&od->d_mutex, NULL, MUTEX_DEFAULT, NULL);
+ od->d_refcnt = 1;
+ od->d_state = SMB_ODIR_STATE_OPEN;
+ od->d_magic = SMB_ODIR_MAGIC;
+ od->d_opened_by_pid = sr->smb_pid;
+ od->d_session = tree->t_session;
+ od->d_user = tree->t_user;
+ od->d_tree = tree;
+ od->d_dnode = dnode;
+ smb_node_ref(dnode);
+ od->d_odid = odid;
+ od->d_sattr = sattr;
+ (void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern));
+ od->d_wildcards = (smb_convert_unicode_wildcards(od->d_pattern) != 0);
+ od->d_is_edp = vfs_has_feature(dnode->vp->v_vfsp, VFSFT_DIRENTFLAGS);
+ od->d_ignore_case =
+ smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE);
+ od->d_eof = B_FALSE;
+
+ smb_llist_enter(&tree->t_odir_list, RW_WRITER);
+ smb_llist_insert_tail(&tree->t_odir_list, od);
+ smb_llist_exit(&tree->t_odir_list);
+
+ atomic_inc_32(&tree->t_session->s_dir_cnt);
+ return (od);
}
/*
* smb_odir_delete
+ *
+ * Removal of the odir from the tree's list of odirs must be
+ * done before any resources associated with the odir are
+ * released.
*/
static void
-smb_odir_delete(
- smb_odir_t *od)
+smb_odir_delete(smb_odir_t *od)
{
ASSERT(od);
ASSERT(od->d_magic == SMB_ODIR_MAGIC);
ASSERT(od->d_state == SMB_ODIR_STATE_CLOSED);
ASSERT(od->d_refcnt == 0);
- /*
- * Let's remove the odir from the list of odirs of the tree. This has
- * to be done before any resources associated with the odir are
- * released.
- */
smb_llist_enter(&od->d_tree->t_odir_list, RW_WRITER);
smb_llist_remove(&od->d_tree->t_odir_list, od);
smb_llist_exit(&od->d_tree->t_odir_list);
+
od->d_magic = 0;
-
- smb_node_release(od->d_dir_snode);
atomic_dec_32(&od->d_tree->t_session->s_dir_cnt);
- smb_idpool_free(&od->d_tree->t_sid_pool, od->d_sid);
+ smb_node_release(od->d_dnode);
+ smb_idpool_free(&od->d_tree->t_odid_pool, od->d_odid);
mutex_destroy(&od->d_mutex);
kmem_cache_free(od->d_tree->t_server->si_cache_odir, od);
}
+
+/*
+ * smb_odir_next_odirent
+ *
+ * Find the next directory entry in d_buf. If d_bufptr is NULL (buffer
+ * is empty or we've reached the end of it), read the next set of
+ * entries from the file system (vop_readdir).
+ *
+ * File systems which support VFSFT_EDIRENT_FLAGS will return the
+ * directory entries as a buffer of edirent_t structure. Others will
+ * return a buffer of dirent64_t structures. For simplicity translate
+ * the data into an smb_odirent_t structure.
+ * The ed_name/d_name in d_buf is NULL terminated by the file system.
+ *
+ * Some file systems can have directories larger than SMB_MAXDIRSIZE.
+ * If the odirent offset >= SMB_MAXDIRSIZE return ENOENT.
+ *
+ * Returns:
+ * 0 - success. odirent is populated with the next directory entry
+ * ENOENT - no more directory entries
+ * errno - error
+ */
+static int
+smb_odir_next_odirent(smb_odir_t *od, smb_odirent_t *odirent)
+{
+ int rc;
+ int reclen;
+ int eof;
+ dirent64_t *dp;
+ edirent_t *edp;
+
+ ASSERT(MUTEX_HELD(&od->d_mutex));
+
+ if (od->d_bufptr != NULL) {
+ reclen = od->d_is_edp ?
+ od->d_edp->ed_reclen : od->d_dp->d_reclen;
+
+ if (reclen == 0) {
+ od->d_bufptr = NULL;
+ } else {
+ od->d_bufptr += reclen;
+ if (od->d_bufptr >= od->d_buf + od->d_bufsize)
+ od->d_bufptr = NULL;
+ }
+ }
+
+ if (od->d_bufptr == NULL) {
+ if (od->d_eof)
+ return (ENOENT);
+
+ od->d_bufsize = sizeof (od->d_buf);
+
+ rc = smb_vop_readdir(od->d_dnode->vp, od->d_offset,
+ od->d_buf, &od->d_bufsize, &eof, od->d_user->u_cred);
+
+ if ((rc == 0) && (od->d_bufsize == 0))
+ rc = ENOENT;
+
+ if (rc != 0) {
+ od->d_bufptr = NULL;
+ od->d_bufsize = 0;
+ return (rc);
+ }
+
+ od->d_eof = (eof != 0);
+ od->d_bufptr = od->d_buf;
+ }
+
+ od->d_offset = (od->d_is_edp) ? od->d_edp->ed_off : od->d_dp->d_off;
+ if (od->d_offset >= SMB_MAXDIRSIZE) {
+ od->d_bufptr = NULL;
+ od->d_bufsize = 0;
+ return (ENOENT);
+ }
+
+ if (od->d_is_edp) {
+ edp = od->d_edp;
+ odirent->od_ino = edp->ed_ino;
+ odirent->od_eflags = edp->ed_eflags;
+ (void) strlcpy(odirent->od_name, edp->ed_name,
+ sizeof (odirent->od_name));
+ } else {
+ dp = od->d_dp;
+ odirent->od_ino = dp->d_ino;
+ odirent->od_eflags = 0;
+ (void) strlcpy(odirent->od_name, dp->d_name,
+ sizeof (odirent->od_name));
+ }
+
+ return (0);
+}
+
+/*
+ * smb_odir_single_fileinfo
+ *
+ * Lookup the file identified by od->d_pattern.
+ *
+ * If the looked up file is a link, we attempt to lookup the link target
+ * to use its attributes in place of those of the files's.
+ * If we fail to lookup the target of the link we use the original
+ * file's attributes.
+ * Check if the attributes match the search attributes.
+ *
+ * Returns: 0 - success
+ * ENOENT - no match
+ * errno - error
+ */
+static int
+smb_odir_single_fileinfo(smb_request_t *sr, smb_odir_t *od,
+ smb_fileinfo_t *fileinfo)
+{
+ int rc;
+ smb_node_t *fnode, *tgt_node;
+ smb_attr_t attr, tgt_attr, *fattr;
+ ino64_t ino;
+ char *name;
+ uint32_t dosattr;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+
+ ASSERT(MUTEX_HELD(&od->d_mutex));
+ bzero(fileinfo, sizeof (smb_fileinfo_t));
+
+ rc = smb_fsop_lookup(sr, od->d_user->u_cred, 0, od->d_tree->t_snode,
+ od->d_dnode, od->d_pattern, &fnode, &attr, 0, 0);
+ if (rc != 0)
+ return (rc);
+
+ name = fnode->od_name;
+
+ (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));
+ ino = attr.sa_vattr.va_nodeid;
+ (void) smb_mangle_name(ino, name,
+ fileinfo->fi_shortname, fileinfo->fi_name83, 0);
+
+ /* follow link to get target node & attr */
+ if ((fnode->vp->v_type == VLNK) &&
+ (smb_odir_lookup_link(sr, od, name, &tgt_node, &tgt_attr))) {
+ smb_node_release(fnode);
+ fnode = tgt_node;
+ fattr = &tgt_attr;
+ } else {
+ fattr = &attr;
+ }
+
+ /* check search attributes */
+ dosattr = smb_node_get_dosattr(fnode);
+ if (!smb_sattr_check(dosattr, od->d_sattr, fileinfo->fi_name)) {
+ smb_node_release(fnode);
+ return (ENOENT);
+ }
+
+ fileinfo->fi_dosattr = dosattr;
+ fileinfo->fi_nodeid = fattr->sa_vattr.va_nodeid;
+ fileinfo->fi_size = smb_node_get_size(fnode, fattr);
+ fileinfo->fi_alloc_size = fattr->sa_vattr.va_nblocks * DEV_BSIZE;
+ fileinfo->fi_atime = fattr->sa_vattr.va_atime;
+ fileinfo->fi_mtime = fattr->sa_vattr.va_mtime;
+ fileinfo->fi_ctime = fattr->sa_vattr.va_ctime;
+ if (fattr->sa_crtime.tv_sec)
+ fileinfo->fi_crtime = fattr->sa_crtime;
+ else
+ fileinfo->fi_crtime = fattr->sa_vattr.va_mtime;
+
+ smb_node_release(fnode);
+ return (0);
+}
+
+/*
+ * smb_odir_wildcard_fileinfo
+ *
+ * odirent contains a directory entry, obtained from a vop_readdir.
+ * If a case conflict is identified the filename is mangled and the
+ * shortname is used as 'name', in place of odirent->od_name. This
+ * name will be used in the smb_fsop_lookup because smb_fsop_lookup
+ * performs a case insensitive lookup if the tree is case insesitive,
+ * so the mangled name is required in the case conflict scenario to
+ * ensure the correct match.
+ *
+ * If the looked up file is a link, we attempt to lookup the link target
+ * to use its attributes in place of those of the files's.
+ * If we fail to lookup the target of the link we use the original
+ * file's attributes.
+ * Check if the attributes match the search attributes.
+ *
+ * Although some file systems can have directories larger than
+ * SMB_MAXDIRSIZE smb_odir_next_odirent ensures that no offset larger
+ * than SMB_MAXDIRSIZE is returned. It is therefore safe to use the
+ * offset as the cookie (uint32_t).
+ *
+ * Returns: 0 - success
+ * ENOENT - no match, proceed to next entry
+ * errno - error
+ */
+static int
+smb_odir_wildcard_fileinfo(smb_request_t *sr, smb_odir_t *od,
+ smb_odirent_t *odirent, smb_fileinfo_t *fileinfo)
+{
+ int rc;
+ smb_node_t *fnode, *tgt_node;
+ smb_attr_t attr, tgt_attr, *fattr;
+ char *name;
+ uint32_t dosattr;
+ boolean_t case_conflict;
+
+ ASSERT(sr);
+ ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+
+ ASSERT(MUTEX_HELD(&od->d_mutex));
+ bzero(fileinfo, sizeof (smb_fileinfo_t));
+
+ case_conflict = ((od->d_ignore_case) &&
+ (odirent->od_eflags & ED_CASE_CONFLICT));
+ (void) smb_mangle_name(odirent->od_ino, odirent->od_name,
+ fileinfo->fi_shortname, fileinfo->fi_name83, case_conflict);
+ name = (case_conflict) ? fileinfo->fi_shortname : odirent->od_name;
+ (void) strlcpy(fileinfo->fi_name, name, sizeof (fileinfo->fi_name));
+
+ rc = smb_fsop_lookup(sr, od->d_user->u_cred, 0, od->d_tree->t_snode,
+ od->d_dnode, name, &fnode, &attr, 0, 0);
+ if (rc != 0)
+ return (rc);
+
+ /* follow link to get target node & attr */
+ if ((fnode->vp->v_type == VLNK) &&
+ (smb_odir_lookup_link(sr, od, name, &tgt_node, &tgt_attr))) {
+ smb_node_release(fnode);
+ fnode = tgt_node;
+ fattr = &tgt_attr;
+ } else {
+ fattr = &attr;
+ }
+
+ /* check search attributes */
+ dosattr = smb_node_get_dosattr(fnode);
+ if (!smb_sattr_check(dosattr, od->d_sattr, fileinfo->fi_name)) {
+ smb_node_release(fnode);
+ return (ENOENT);
+ }
+
+ fileinfo->fi_cookie = (uint32_t)od->d_offset;
+ fileinfo->fi_dosattr = dosattr;
+ fileinfo->fi_nodeid = fattr->sa_vattr.va_nodeid;
+ fileinfo->fi_size = smb_node_get_size(fnode, fattr);
+ fileinfo->fi_alloc_size = fattr->sa_vattr.va_nblocks * DEV_BSIZE;
+ fileinfo->fi_atime = fattr->sa_vattr.va_atime;
+ fileinfo->fi_mtime = fattr->sa_vattr.va_mtime;
+ fileinfo->fi_ctime = fattr->sa_vattr.va_ctime;
+ if (fattr->sa_crtime.tv_sec)
+ fileinfo->fi_crtime = fattr->sa_crtime;
+ else
+ fileinfo->fi_crtime = fattr->sa_vattr.va_mtime;
+
+ smb_node_release(fnode);
+ return (0);
+}
+
+/*
+ * smb_odir_lookup_link
+ *
+ * If the file is a symlink we lookup the object to which the
+ * symlink refers so that we can return its attributes.
+ * This can cause a problem if a symlink in a sub-directory
+ * points to a parent directory (some UNIX GUI's create a symlink
+ * in $HOME/.desktop that points to the user's home directory).
+ * Some Windows applications (e.g. virus scanning) loop/hang
+ * trying to follow this recursive path and there is little
+ * we can do because the path is constructed on the client.
+ * smb_dirsymlink_enable allows an end-user to disable
+ * symlinks to directories. Symlinks to other object types
+ * should be unaffected.
+ *
+ * Returns: B_TRUE - followed link. tgt_node and tgt_attr set
+ * B_FALSE - link not followed
+ */
+static boolean_t
+smb_odir_lookup_link(smb_request_t *sr, smb_odir_t *od,
+ char *fname, smb_node_t **tgt_node, smb_attr_t *tgt_attr)
+{
+ int rc;
+
+ rc = smb_fsop_lookup(sr, od->d_user->u_cred, SMB_FOLLOW_LINKS,
+ od->d_tree->t_snode, od->d_dnode, fname, tgt_node, tgt_attr, 0, 0);
+ if (rc != 0) {
+ *tgt_node = NULL;
+ return (B_FALSE);
+ }
+
+ if ((tgt_attr->sa_vattr.va_type == VDIR) && (!smb_dirsymlink_enable)) {
+ smb_node_release(*tgt_node);
+ *tgt_node = NULL;
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c Sun Feb 01 19:44:54 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.
*/
@@ -31,6 +31,7 @@
#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_fsops.h>
+#include <inet/tcp.h>
/*
* Oplock functionality enable/disable
@@ -338,7 +339,8 @@
node->n_oplock.op_flags &=
~OPLOCK_FLAG_BREAKING;
node->n_oplock.op_ofile = NULL;
- node->n_oplock.op_ipaddr = 0;
+ bzero(&node->n_oplock.op_ipaddr,
+ sizeof (node->n_oplock.op_ipaddr));
node->n_oplock.op_kid = 0;
smb_rwx_rwexit(&node->n_lock);
@@ -427,7 +429,7 @@
node->flags &= ~NODE_OPLOCKS_IN_FORCE;
node->n_oplock.op_flags &= ~OPLOCK_FLAG_BREAKING;
node->n_oplock.op_ofile = NULL;
- node->n_oplock.op_ipaddr = 0;
+ bzero(&node->n_oplock.op_ipaddr, sizeof (node->n_oplock.op_ipaddr));
node->n_oplock.op_kid = 0;
if (!have_rwx)
--- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c Sun Feb 01 19:44:54 2009 -0700
@@ -494,14 +494,16 @@
if (++nlink > MAXSYMLINKS) {
err = ELOOP;
+ VN_RELE(vp);
break;
}
(void) pn_alloc(&link_pn);
err = pn_getsymlink(vp, &link_pn, cred);
+ VN_RELE(vp);
if (err) {
- (void) pn_free(&link_pn);
+ pn_free(&link_pn);
break;
}
@@ -537,6 +539,7 @@
fnode = smb_node_lookup(sr, NULL, cred, vp, namep,
dnode, NULL, &attr);
+ VN_RELE(vp);
if (fnode == NULL) {
err = ENOMEM;
@@ -548,6 +551,7 @@
upn.pn_path++;
upn.pn_pathlen--;
}
+
}
/*
--- a/usr/src/uts/common/fs/smbsrv/smb_search.c Sun Feb 01 15:33:03 2009 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +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.
- */
-
-#pragma ident "@(#)smb_search.c 1.9 08/08/07 SMI"
-
-/*
- * SMB: search
- *
- * This command is used to search directories.
- *
- * Client Request Description
- * ================================== =================================
- *
- * UCHAR WordCount; Count of parameter words = 2
- * USHORT MaxCount; Number of dir. entries to return
- * USHORT SearchAttributes;
- * USHORT ByteCount; Count of data bytes; min = 5
- * UCHAR BufferFormat1; 0x04 -- ASCII
- * UCHAR FileName[]; File name, may be null
- * UCHAR BufferFormat2; 0x05 -- Variable block
- * USHORT ResumeKeyLength; Length of resume key, may be 0
- * UCHAR ResumeKey[]; Resume key
- *
- * FileName specifies the file to be sought. SearchAttributes indicates
- * the attributes that the file must have, and is described in the "File
- * Attribute Encoding" section of this document. If SearchAttributes is
- * zero then only normal files are returned. If the system file, hidden or
- * directory attributes are specified then the search is inclusive@both the
- * specified type(s) of files and normal files are returned. If the volume
- * label attribute is specified then the search is exclusive, and only the
- * volume label entry is returned.
- *
- * MaxCount specifies the number of directory entries to be returned.
- *
- * Server Response Description
- * ================================== =================================
- *
- * UCHAR WordCount; Count of parameter words = 1
- * USHORT Count; Number of entries returned
- * USHORT ByteCount; Count of data bytes; min = 3
- * UCHAR BufferFormat; 0x05 -- Variable block
- * USHORT DataLength; Length of data
- * UCHAR DirectoryInformationData[]; Data
- *
- * The response will contain one or more directory entries as determined by
- * the Count field. No more than MaxCount entries will be returned. Only
- * entries that match the sought FileName and SearchAttributes combination
- * will be returned.
- *
- * ResumeKey must be null (length = 0) on the initial search request.
- * Subsequent search requests intended to continue a search must contain
- * the ResumeKey field extracted from the last directory entry of the
- * previous response. ResumeKey is self-contained, for on calls containing
- * a non-zero ResumeKey neither the SearchAttributes or FileName fields
- * will be valid in the request. ResumeKey has the following format:
- *
- * Resume Key Field Description
- * ================================== =================================
- *
- * UCHAR Reserved; bit 7 - consumer use
- * bits 5,6 - system use (must
- * preserve)
- * bits 0-4 - server use (must
- * preserve)
- * UCHAR FileName[11]; Name of the returned file
- * UCHAR ReservedForServer[5]; Client must not modify
- * UCHAR ReservedForConsumer[4]; Server must not modify
- *
- * FileName is 8.3 format, with the three character extension left
- * justified into FileName[9-11]. If the client is prior to the LANMAN1.0
- * dialect, the returned FileName should be uppercased.
- *
- * SMB_COM_SEARCH terminates when either the requested maximum number of
- * entries that match the named file are found, or the end of directory is
- * reached without the maximum number of matches being found. A response
- * containing no entries indicates that no matching entries were found
- * between the starting point of the search and the end of directory.
- *
- * There may be multiple matching entries in response to a single request
- * as SMB_COM_SEARCH supports wildcards in the last component of FileName
- * of the initial request.
- *
- * Returned directory entries in the DirectoryInformationData field of the
- * response each have the following format:
- *
- * Directory Information Field Description
- * ================================== =================================
- *
- * SMB_RESUME_KEY ResumeKey; Described above
- * UCHAR FileAttributes; Attributes of the found file
- * SMB_TIME LastWriteTime; Time file was last written
- * SMB_DATE LastWriteDate; Date file was last written
- * ULONG FileSize; Size of the file
- * UCHAR FileName[13]; ASCII, space-filled null
- * terminated
- *
- * FileName must conform to 8.3 rules, and is padded after the extension
- * with 0x20 characters if necessary. If the client has negotiated a
- * dialect prior to the LANMAN1.0 dialect, or if bit0 of the Flags2 SMB
- * header field of the request is clear, the returned FileName should be
- * uppercased.
- *
- * As can be seen from the above structure, SMB_COM_SEARCH can not return
- * long filenames, and can not return UNICODE filenames. Files which have
- * a size greater than 2^32 bytes should have the least significant 32 bits
- * of their size returned in FileSize.
- */
-
-#include <smbsrv/smb_incl.h>
-
-smb_sdrc_t
-smb_pre_search(smb_request_t *sr)
-{
- DTRACE_SMB_1(op__Search__start, smb_request_t *, sr);
- return (SDRC_SUCCESS);
-}
-
-void
-smb_post_search(smb_request_t *sr)
-{
- DTRACE_SMB_1(op__Search__done, smb_request_t *, sr);
-}
-
-smb_sdrc_t
-smb_com_search(smb_request_t *sr)
-{
- int rc;
- unsigned short sattr, count, maxcount;
- char *path;
- uint16_t index;
- uint32_t cookie;
- char name[SMB_SHORTNAMELEN];
- unsigned char resume_char;
- uint32_t client_key;
- smb_tree_t *tree;
- smb_node_t *node;
- unsigned char type;
- unsigned short key_len;
- smb_odir_context_t *pc;
- boolean_t find_first = B_TRUE;
- boolean_t to_upper = B_FALSE;
-
- if ((sr->session->dialect <= LANMAN1_0) ||
- ((sr->smb_flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES) == 0)) {
- to_upper = B_TRUE;
- }
-
- /* We only handle 8.3 name here */
- sr->smb_flg2 &= ~SMB_FLAGS2_KNOWS_LONG_NAMES;
- sr->smb_flg &= ~SMB_FLAGS_CASE_INSENSITIVE;
-
- if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
- return (SDRC_ERROR);
-
- rc = smbsr_decode_data(sr, "%Abw", sr, &path, &type, &key_len);
- if ((rc != 0) || (type != 0x05))
- return (SDRC_ERROR);
-
- tree = sr->tid_tree;
- count = 0;
-
- if ((sattr == FILE_ATTRIBUTE_VOLUME) && (key_len != 21)) {
- (void) memset(name, ' ', sizeof (name));
- (void) strncpy(name, tree->t_volume, sizeof (name));
-
- if (key_len >= 21) {
- (void) smb_mbc_decodef(&sr->smb_data, "17.l",
- &client_key);
- } else {
- client_key = 0;
- }
-
- (void) smb_mbc_encodef(&sr->reply, "bwwbwb11c5.lb8.13c",
- 1, 0, VAR_BCC, 5, 0, 0, path+1,
- client_key, sattr, name);
- count++;
- } else {
- index = 0;
- cookie = 0;
-
- if (key_len == 0) { /* begin search */
- /*
- * Some MS clients pass NULL file names
- * NT interprets this as "\"
- */
- if (strlen(path) == 0) path = "\\";
-
- rc = smb_rdir_open(sr, path, sattr);
- if (rc == -1)
- return (SDRC_ERROR);
- if (rc == -2) {
- sr->reply.chain_offset = sr->cur_reply_offset;
- (void) smb_mbc_encodef(&sr->reply, "bw", 0, 0);
- return (SDRC_SUCCESS);
- }
- resume_char = 0;
- client_key = 0;
- } else if (key_len == 21) {
- if (smb_mbc_decodef(&sr->smb_data, "b12.wwl",
- &resume_char, &index, &sr->smb_sid, &client_key)
- != 0) {
- /* We don't know which search to close! */
- return (SDRC_ERROR);
- }
-
- sr->sid_odir = smb_odir_lookup_by_sid(tree,
- sr->smb_sid);
- if (sr->sid_odir == NULL) {
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
- ERRDOS, ERRbadfid);
- return (SDRC_ERROR);
- }
- cookie = sr->sid_odir->d_cookies[index];
- if (cookie != 0)
- find_first = B_FALSE;
- } else {
- /* We don't know which search to close! */
- return (SDRC_ERROR);
- }
-
- (void) smb_mbc_encodef(&sr->reply, "bwwbw", 1, 0,
- VAR_BCC, 5, 0);
-
- pc = kmem_zalloc(sizeof (smb_odir_context_t), KM_SLEEP);
- pc->dc_cookie = cookie;
- node = NULL;
- rc = 0;
- index = 0;
-
- if (maxcount > SMB_MAX_SEARCH)
- maxcount = SMB_MAX_SEARCH;
-
- while (count < maxcount) {
- if ((rc = smb_rdir_next(sr, &node, pc)) != 0)
- break;
-
- if (smb_is_dot_or_dotdot(pc->dc_name)) {
- if (node) {
- smb_node_release(node);
- node = NULL;
- }
- continue;
- }
-
- (void) memset(name, ' ', sizeof (name));
- if (*pc->dc_shortname) {
- (void) strlcpy(name, pc->dc_shortname,
- SMB_SHORTNAMELEN - 1);
- } else {
- (void) strlcpy(name, pc->dc_name,
- SMB_SHORTNAMELEN - 1);
- if (to_upper)
- (void) utf8_strupr(name);
- }
-
- (void) smb_mbc_encodef(&sr->reply, "b8c3c.wwlbYl13c",
- resume_char,
- pc->dc_name83, pc->dc_name83+9,
- index, sr->smb_sid, client_key,
- pc->dc_dattr & 0xff,
- smb_gmt2local(sr,
- pc->dc_attr.sa_vattr.va_mtime.tv_sec),
- (int32_t)smb_node_get_size(node, &pc->dc_attr),
- name);
- smb_node_release(node);
- node = NULL;
- sr->sid_odir->d_cookies[index] = pc->dc_cookie;
- count++;
- index++;
- }
-
- kmem_free(pc, sizeof (smb_odir_context_t));
-
- if ((rc != 0) && (rc != ENOENT)) {
- /* returned error by smb_rdir_next() */
- smb_rdir_close(sr);
- smbsr_errno(sr, rc);
- return (SDRC_ERROR);
- }
-
- if (count == 0 && find_first) {
- smb_rdir_close(sr);
- smbsr_warn(sr, NT_STATUS_NO_MORE_FILES,
- ERRDOS, ERROR_NO_MORE_FILES);
- return (SDRC_ERROR);
- }
- }
-
- rc = (sr->reply.chain_offset - sr->cur_reply_offset) - 8;
- (void) smb_mbc_poke(&sr->reply, sr->cur_reply_offset, "bwwbw",
- 1, count, rc+3, 5, rc);
-
- return (SDRC_SUCCESS);
-}
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c Sun Feb 01 19:44:54 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.
*/
@@ -233,7 +233,7 @@
static int smb_server_kstat_update_info(kstat_t *, int);
static void smb_server_timers(smb_thread_t *, void *);
static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *,
- in_port_t, int);
+ in_port_t, int, int);
static int smb_server_lookup(smb_server_t **);
static void smb_server_release(smb_server_t *);
static int smb_server_ulist_geti(smb_session_list_t *, int,
@@ -563,7 +563,7 @@
sv->sv_cfg.skc_maxworkers, INT_MAX,
TASKQ_DYNAMIC|TASKQ_PREPOPULATE);
- sv->sv_session = smb_session_create(NULL, 0, sv);
+ sv->sv_session = smb_session_create(NULL, 0, sv, 0);
if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) {
rc = ENOMEM;
@@ -666,8 +666,11 @@
}
mutex_exit(&sv->sv_mutex);
+ /*
+ * netbios must be ipv4
+ */
rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT,
- error);
+ AF_INET, error);
if (rc) {
mutex_enter(&sv->sv_mutex);
@@ -711,9 +714,12 @@
}
mutex_exit(&sv->sv_mutex);
- rc = smb_server_listen(sv, &sv->sv_tcp_daemon, SMB_SRVC_TCP_PORT,
- error);
-
+ if (sv->sv_cfg.skc_ipv6_enable)
+ rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
+ SMB_SRVC_TCP_PORT, AF_INET6, error);
+ else
+ rc = smb_server_listen(sv, &sv->sv_tcp_daemon,
+ SMB_SRVC_TCP_PORT, AF_INET, error);
if (rc) {
mutex_enter(&sv->sv_mutex);
sv->sv_tcp_daemon.ld_kth = NULL;
@@ -1239,6 +1245,7 @@
smb_server_t *sv,
smb_listener_daemon_t *ld,
in_port_t port,
+ int family,
int pthread_create_error)
{
int rc;
@@ -1256,21 +1263,31 @@
if (ld->ld_so == NULL) {
/* First time listener */
- ld->ld_sin.sin_family = AF_INET;
- ld->ld_sin.sin_port = htons(port);
- ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
- ld->ld_so = smb_socreate(AF_INET, SOCK_STREAM, 0);
-
+ if (family == AF_INET) {
+ ld->ld_sin.sin_family = (uint32_t)family;
+ ld->ld_sin.sin_port = htons(port);
+ ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ ld->ld_sin6.sin6_family = (uint32_t)family;
+ ld->ld_sin6.sin6_port = htons(port);
+ (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0,
+ sizeof (ld->ld_sin6.sin6_addr.s6_addr));
+ }
+ ld->ld_so = smb_socreate(family, SOCK_STREAM, 0);
if (ld->ld_so) {
(void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET,
SO_REUSEADDR, (const void *)&on, sizeof (on),
CRED());
-
- rc = ksocket_bind(ld->ld_so,
- (struct sockaddr *)&ld->ld_sin,
- sizeof (ld->ld_sin), CRED());
-
+ if (family == AF_INET) {
+ rc = ksocket_bind(ld->ld_so,
+ (struct sockaddr *)&ld->ld_sin,
+ sizeof (ld->ld_sin), CRED());
+ } else {
+ rc = ksocket_bind(ld->ld_so,
+ (struct sockaddr *)&ld->ld_sin6,
+ sizeof (ld->ld_sin6), CRED());
+ }
if (rc == 0) {
rc = ksocket_listen(ld->ld_so, 20, CRED());
if (rc < 0) {
@@ -1318,7 +1335,7 @@
/*
* Create a session for this connection.
*/
- session = smb_session_create(s_so, port, sv);
+ session = smb_session_create(s_so, port, sv, family);
if (session) {
smb_session_list_append(&ld->ld_session_list,
session);
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c Sun Feb 01 19:44:54 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,6 +32,7 @@
#include <smbsrv/netbios.h>
#include <smbsrv/smb_incl.h>
#include <smbsrv/smb_i18n.h>
+#include <inet/tcp.h>
static volatile uint64_t smb_kids;
@@ -42,7 +43,7 @@
uint8_t *, size_t);
static smb_user_t *smb_session_lookup_user(smb_session_t *, char *, char *);
static void smb_request_init_command_mbuf(smb_request_t *sr);
-
+void dump_smb_inaddr(smb_inaddr_t *ipaddr);
void
smb_session_timers(smb_session_list_t *se)
@@ -120,7 +121,7 @@
* there is no NetBIOS name. See also Knowledge Base article Q301673.
*/
void
-smb_session_reconnection_check(smb_session_list_t *se, smb_session_t *session)
+smb_session_reconnection_check(smb_session_list_t *se, smb_session_t *sess)
{
smb_session_t *sn;
@@ -128,12 +129,14 @@
sn = list_head(&se->se_act.lst);
while (sn) {
ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
- if ((sn != session) &&
- (sn->ipaddr == session->ipaddr) &&
- (sn->local_ipaddr == session->local_ipaddr) &&
- (strcasecmp(sn->workstation, session->workstation) == 0) &&
- (sn->opentime <= session->opentime) &&
- (sn->s_kid < session->s_kid)) {
+ if ((sn != sess) &&
+ smb_inet_equal(&sn->ipaddr, &sess->ipaddr,
+ SMB_INET_NOMASK) &&
+ smb_inet_equal(&sn->local_ipaddr, &sess->local_ipaddr,
+ SMB_INET_NOMASK) &&
+ (strcasecmp(sn->workstation, sess->workstation) == 0) &&
+ (sn->opentime <= sess->opentime) &&
+ (sn->s_kid < sess->s_kid)) {
tsignal(sn->s_thread, SIGINT);
}
sn = list_next(&se->se_act.lst, sn);
@@ -323,8 +326,8 @@
ret_hdr->xh_type = buf[0];
if (ret_hdr->xh_type != 0) {
- cmn_err(CE_WARN, "0x%08x: invalid type (%u)",
- session->ipaddr, ret_hdr->xh_type);
+ cmn_err(CE_WARN, "invalid type (%u)", ret_hdr->xh_type);
+ dump_smb_inaddr(&session->ipaddr);
return (EPROTO);
}
@@ -334,8 +337,8 @@
break;
default:
- cmn_err(CE_WARN, "0x%08x: invalid port %u",
- session->ipaddr, session->s_local_port);
+ cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
+ dump_smb_inaddr(&session->ipaddr);
return (EPROTO);
}
@@ -371,8 +374,8 @@
break;
default:
- cmn_err(CE_WARN, "0x%08x: invalid port (%u)",
- session->ipaddr, session->s_local_port);
+ cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
+ dump_smb_inaddr(&session->ipaddr);
return (-1);
}
@@ -634,10 +637,12 @@
* Port will be SSN_SRVC_TCP_PORT or SMB_SRVC_TCP_PORT.
*/
smb_session_t *
-smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv)
+smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
+ int family)
{
struct sockaddr_in sin;
socklen_t slen;
+ struct sockaddr_in6 sin6;
smb_session_t *session;
session = kmem_cache_alloc(sv->si_cache_session, KM_SLEEP);
@@ -669,17 +674,25 @@
smb_rwx_init(&session->s_lock);
if (new_so) {
- slen = sizeof (sin);
-
- (void) ksocket_getsockname(new_so, (struct sockaddr *)&sin,
- &slen, CRED());
- session->local_ipaddr = sin.sin_addr.s_addr;
-
- slen = sizeof (sin);
- (void) ksocket_getpeername(new_so, (struct sockaddr *)&sin,
- &slen, CRED());
- session->ipaddr = sin.sin_addr.s_addr;
-
+ if (family == AF_INET) {
+ slen = sizeof (sin);
+ (void) ksocket_getsockname(new_so,
+ (struct sockaddr *)&sin, &slen, CRED());
+ bcopy(&sin, &session->local_ipaddr.a_ip, slen);
+ (void) ksocket_getpeername(new_so,
+ (struct sockaddr *)&sin, &slen, CRED());
+ bcopy(&sin6, &session->ipaddr.a_ip, slen);
+ } else {
+ slen = sizeof (sin6);
+ (void) ksocket_getsockname(new_so,
+ (struct sockaddr *)&sin6, &slen, CRED());
+ bcopy(&sin, &session->local_ipaddr.a_ip, slen);
+ (void) ksocket_getpeername(new_so,
+ (struct sockaddr *)&sin6, &slen, CRED());
+ bcopy(&sin6, &session->ipaddr.a_ip, slen);
+ }
+ session->ipaddr.a_family = family;
+ session->local_ipaddr.a_family = family;
session->s_local_port = port;
session->sock = new_so;
}
@@ -1105,7 +1118,6 @@
ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
ASSERT(sr->session);
ASSERT(sr->fid_ofile == NULL);
- ASSERT(sr->sid_odir == NULL);
ASSERT(sr->r_xa == NULL);
if (sr->tid_tree)
@@ -1134,3 +1146,14 @@
mutex_destroy(&sr->sr_mutex);
kmem_cache_free(sr->sr_cache, sr);
}
+
+void
+dump_smb_inaddr(smb_inaddr_t *ipaddr)
+{
+char ipstr[INET6_ADDRSTRLEN];
+
+ if (smb_inet_ntop(ipaddr, ipstr, SMB_IPSTRLEN(ipaddr->a_family)))
+ cmn_err(CE_WARN, "error ipstr=%s", ipstr);
+ else
+ cmn_err(CE_WARN, "error converting ip address");
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c Sun Feb 01 19:44:54 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.
*/
/*
@@ -226,6 +226,29 @@
#include <smbsrv/smb_token.h>
#include <smbsrv/smb_door_svc.h>
+typedef struct smb_sessionsetup_info {
+ char *ssi_user;
+ char *ssi_domain;
+ char *ssi_native_os;
+ char *ssi_native_lm;
+ uint16_t ssi_cipwlen;
+ uint8_t *ssi_cipwd;
+ uint16_t ssi_cspwlen;
+ uint8_t *ssi_cspwd;
+ uint16_t ssi_maxbufsize;
+ uint16_t ssi_maxmpxcount;
+ uint16_t ssi_vcnumber;
+ uint32_t ssi_capabilities;
+ uint32_t ssi_sesskey;
+} smb_sessionsetup_info_t;
+
+#define SMB_AUTH_FAILED -1
+#define SMB_AUTH_USER 0
+#define SMB_AUTH_GUEST 1
+
+static int smb_authenticate(smb_request_t *, smb_sessionsetup_info_t *,
+ smb_session_key_t **);
+
smb_sdrc_t
smb_pre_session_setup_andx(smb_request_t *sr)
{
@@ -242,41 +265,26 @@
smb_sdrc_t
smb_com_session_setup_andx(smb_request_t *sr)
{
- uint16_t maxbufsize, maxmpxcount, vcnumber = 0;
- uint32_t sesskey;
- uint32_t capabilities = 0;
- char *username = "";
- char *userdomain = "";
- char *native_os = "";
- char *native_lanman = "";
- char *hostname = sr->sr_cfg->skc_hostname;
- char *nbdomain = sr->sr_cfg->skc_nbdomain;
- char *fqdn = sr->sr_cfg->skc_fqdn;
- smb_token_t *usr_token = NULL;
- smb_user_t *user = NULL;
- int security = sr->sr_cfg->skc_secmode;
+ smb_sessionsetup_info_t sinfo;
+ smb_session_key_t *session_key = NULL;
+ char ipaddr_buf[INET6_ADDRSTRLEN];
+ int auth_res;
+ int rc;
- uint16_t ci_pwlen = 0;
- unsigned char *ci_password = NULL;
- uint16_t cs_pwlen = 0;
- unsigned char *cs_password = NULL;
-
- netr_client_t clnt_info;
- smb_session_key_t *session_key = NULL;
- int rc;
- char ipaddr_buf[INET6_ADDRSTRLEN];
- boolean_t known_domain;
+ bzero(&sinfo, sizeof (smb_sessionsetup_info_t));
if (sr->session->dialect >= NT_LM_0_12) {
rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com,
- &sr->andx_off, &maxbufsize, &maxmpxcount, &vcnumber,
- &sesskey, &ci_pwlen, &cs_pwlen, &capabilities);
+ &sr->andx_off, &sinfo.ssi_maxbufsize,
+ &sinfo.ssi_maxmpxcount, &sinfo.ssi_vcnumber,
+ &sinfo.ssi_sesskey, &sinfo.ssi_cipwlen,
+ &sinfo.ssi_cspwlen, &sinfo.ssi_capabilities);
if (rc != 0)
return (SDRC_ERROR);
- ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP);
- cs_password = kmem_alloc(cs_pwlen + 1, KM_SLEEP);
+ sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
+ sinfo.ssi_cspwd = kmem_alloc(sinfo.ssi_cspwlen + 1, KM_SLEEP);
/*
* The padding between the Native OS and Native LM is a
@@ -293,27 +301,30 @@
*/
rc = smbsr_decode_data(sr, "%#c#cuuu",
sr,
- ci_pwlen, ci_password,
- cs_pwlen, cs_password,
- &username,
- &userdomain,
- &native_os);
+ sinfo.ssi_cipwlen, sinfo.ssi_cipwd,
+ sinfo.ssi_cspwlen, sinfo.ssi_cspwd,
+ &sinfo.ssi_user,
+ &sinfo.ssi_domain,
+ &sinfo.ssi_native_os);
if (rc != 0) {
- kmem_free(ci_password, ci_pwlen + 1);
- kmem_free(cs_password, cs_pwlen + 1);
+ kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
+ kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
return (SDRC_ERROR);
}
- ci_password[ci_pwlen] = 0;
- cs_password[cs_pwlen] = 0;
+ sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;
+ sinfo.ssi_cspwd[sinfo.ssi_cspwlen] = 0;
- sr->session->native_os = smbnative_os_value(native_os);
+ sr->session->native_os =
+ smbnative_os_value(sinfo.ssi_native_os);
if (sr->session->native_os == NATIVE_OS_WINNT)
- rc = smbsr_decode_data(sr, "%,u", sr, &native_lanman);
+ rc = smbsr_decode_data(sr, "%,u", sr,
+ &sinfo.ssi_native_lm);
else
- rc = smbsr_decode_data(sr, "%u", sr, &native_lanman);
+ rc = smbsr_decode_data(sr, "%u", sr,
+ &sinfo.ssi_native_lm);
/*
* Native Lanman could be null so we really don't care
@@ -321,24 +332,26 @@
* the field we set it to Win NT.
*/
if (rc != 0)
- native_lanman = "NT LAN Manager 4.0";
-
+ sinfo.ssi_native_lm = "NT LAN Manager 4.0";
} else {
rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
- &sr->andx_off, &maxbufsize, &maxmpxcount,
- &vcnumber, &sesskey, &ci_pwlen);
+ &sr->andx_off, &sinfo.ssi_maxbufsize,
+ &sinfo.ssi_maxmpxcount,
+ &sinfo.ssi_vcnumber, &sinfo.ssi_sesskey,
+ &sinfo.ssi_cipwlen);
if (rc != 0)
return (SDRC_ERROR);
- ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP);
- rc = smbsr_decode_data(sr, "%#c", sr, ci_pwlen, ci_password);
+ sinfo.ssi_cipwd = kmem_alloc(sinfo.ssi_cipwlen + 1, KM_SLEEP);
+ rc = smbsr_decode_data(sr, "%#c", sr, sinfo.ssi_cipwlen,
+ sinfo.ssi_cipwd);
if (rc != 0) {
- kmem_free(ci_password, ci_pwlen + 1);
+ kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
return (SDRC_ERROR);
}
- ci_password[ci_pwlen] = 0;
+ sinfo.ssi_cipwd[sinfo.ssi_cipwlen] = 0;
/*
* Despite the CIFS/1.0 spec, the rest of this message is
@@ -346,191 +359,50 @@
* name and the primary domain but we don't care about the
* the native OS or native LanMan fields.
*/
- if (smbsr_decode_data(sr, "%u", sr, &username) != 0)
- username = "";
+ if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_user) != 0)
+ sinfo.ssi_user = "";
- if (smbsr_decode_data(sr, "%u", sr, &userdomain) != 0)
- userdomain = "";
+ if (smbsr_decode_data(sr, "%u", sr, &sinfo.ssi_domain) != 0)
+ sinfo.ssi_domain = "";
sr->session->native_os = NATIVE_OS_UNKNOWN;
}
/*
- * If the vcnumber is zero, we can discard any
+ * If the sinfo.ssi_vcnumber is zero, we can discard any
* other connections associated with this client.
*/
- sr->session->vcnumber = vcnumber;
- if (vcnumber == 0)
+ sr->session->vcnumber = sinfo.ssi_vcnumber;
+ if (sinfo.ssi_vcnumber == 0)
smb_server_reconnection_check(sr->sr_server, sr->session);
- sr->session->smb_msg_size = maxbufsize;
-
- bzero(&clnt_info, sizeof (netr_client_t));
-
- /*
- * Both local and domain users can be authenticated in
- * domain mode. Whether a user is local or not is determined
- * by given domain name in the request. If client does not
- * specify the domain name, both local and domain
- * authentications should be tried. The preferred order is to
- * try the local authentication first.
- */
- known_domain = B_TRUE;
- if (*userdomain == 0) {
- userdomain = hostname;
- if (security == SMB_SECMODE_DOMAIN)
- known_domain = B_FALSE;
- }
-
- if ((cs_pwlen == 0) &&
- (ci_pwlen == 0 || (ci_pwlen == 1 && *ci_password == 0))) {
- /* anonymous user */
- clnt_info.flags |= NETR_CFLG_ANON;
- username = "nobody";
- } else if (*username == '\0') {
- if (ci_password)
- kmem_free(ci_password, ci_pwlen + 1);
- if (cs_password)
- kmem_free(cs_password, cs_pwlen + 1);
- smbsr_error(sr, 0, ERRSRV, ERRaccess);
- return (SDRC_ERROR);
- } else if (security == SMB_SECMODE_DOMAIN) {
- /*
- * If the system is running in domain mode, domain
- * authentication will be performed only when the client
- * sends the domain that matches either the NetBIOS name
- * or FQDN of the domain. Otherwise, local authentication
- * will be performed.
- */
- if (utf8_strcasecmp(userdomain, nbdomain) == 0 ||
- utf8_strcasecmp(userdomain, fqdn) == 0)
- clnt_info.flags |= NETR_CFLG_DOMAIN;
- else
- clnt_info.flags |= NETR_CFLG_LOCAL;
- } else if (security == SMB_SECMODE_WORKGRP) {
- clnt_info.flags |= NETR_CFLG_LOCAL;
- }
-
- /*
- * If the domain is unknown, we are unable to determine
- * whether the specified user is local or domain until
- * the authentication has taken place; thus, the user
- * lookup will be postponed until the user is successfully
- * authenticated.
- */
- if (known_domain)
- user = smb_session_dup_user(sr->session,
- (clnt_info.flags & NETR_CFLG_LOCAL) ?
- hostname : nbdomain, username);
-
- if (user == NULL) {
- cred_t *cr;
- uint32_t privileges;
+ sr->session->smb_msg_size = sinfo.ssi_maxbufsize;
- clnt_info.logon_level = NETR_NETWORK_LOGON;
- clnt_info.domain = userdomain;
- clnt_info.username = username;
- clnt_info.workstation = sr->session->workstation;
- clnt_info.ipaddr = sr->session->ipaddr;
- clnt_info.local_ipaddr = sr->session->local_ipaddr;
- clnt_info.challenge_key.challenge_key_val =
- sr->session->challenge_key;
- clnt_info.challenge_key.challenge_key_len =
- sr->session->challenge_len;
- clnt_info.nt_password.nt_password_val = cs_password;
- clnt_info.nt_password.nt_password_len = cs_pwlen;
- clnt_info.lm_password.lm_password_val = ci_password;
- clnt_info.lm_password.lm_password_len = ci_pwlen;
- clnt_info.native_os = sr->session->native_os;
- clnt_info.native_lm = smbnative_lm_value(native_lanman);
- clnt_info.local_port = sr->session->s_local_port;
-
- DTRACE_PROBE1(smb__sessionsetup__clntinfo, netr_client_t *,
- &clnt_info);
-
- usr_token = smb_upcall_get_token(&clnt_info);
-
- /*
- * If the domain is unknown and we fail to authenticate
- * the user locally, pass-through authentication will be
- * attempted.
- */
- if (!known_domain) {
- if (usr_token == NULL) {
- clnt_info.domain = nbdomain;
- clnt_info.flags &= ~NETR_CFLG_LOCAL;
- clnt_info.flags |= NETR_CFLG_DOMAIN;
- usr_token = smb_upcall_get_token(&clnt_info);
- }
-
- /*
- * Now that the user has successfully been
- * authenticated, the clnt_info.domain is valid.
- * Try to see if the user has already logged in from
- * this session.
- *
- * If this is a subsequent login, a duplicate user
- * instance will be returned. Otherwise, NULL is
- * returned.
- */
- if (usr_token != NULL)
- user = smb_session_dup_user(sr->session,
- clnt_info.domain, username);
- }
-
-
- /* authentication fails */
- if (usr_token == NULL) {
- if (ci_password)
- kmem_free(ci_password, ci_pwlen + 1);
- if (cs_password)
- kmem_free(cs_password, cs_pwlen + 1);
- smbsr_error(sr, 0, ERRSRV, ERRbadpw);
- return (SDRC_ERROR);
- }
-
- if (usr_token->tkn_session_key) {
- session_key = kmem_alloc(sizeof (smb_session_key_t),
- KM_SLEEP);
- (void) memcpy(session_key, usr_token->tkn_session_key,
- sizeof (smb_session_key_t));
- }
-
- /* first login */
- if (user == NULL) {
- cr = smb_cred_create(usr_token, &privileges);
- if (cr != NULL) {
- user = smb_user_login(sr->session, cr,
- usr_token->tkn_domain_name,
- usr_token->tkn_account_name,
- usr_token->tkn_flags,
- privileges,
- usr_token->tkn_audit_sid);
- smb_cred_rele(user->u_cred);
-
- if (user->u_privcred)
- smb_cred_rele(user->u_privcred);
- }
- }
- smb_token_free(usr_token);
- }
-
- if (ci_password)
- kmem_free(ci_password, ci_pwlen + 1);
-
- if (user == NULL) {
- if (session_key)
- kmem_free(session_key, sizeof (smb_session_key_t));
- if (cs_password)
- kmem_free(cs_password, cs_pwlen + 1);
- smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
+ if ((sinfo.ssi_cspwlen == 0) &&
+ (sinfo.ssi_cipwlen == 0 ||
+ (sinfo.ssi_cipwlen == 1 && *sinfo.ssi_cipwd == 0))) {
+ sinfo.ssi_user = "anonymous";
+ } else if (*sinfo.ssi_user == '\0') {
+ if (sinfo.ssi_cipwd)
+ kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
+ if (sinfo.ssi_cspwd)
+ kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
+ smbsr_error(sr, 0, ERRSRV, ERRaccess);
return (SDRC_ERROR);
}
- sr->user_cr = user->u_cred;
- sr->smb_uid = user->u_uid;
- sr->uid_user = user;
- sr->session->capabilities = capabilities;
+ auth_res = smb_authenticate(sr, &sinfo, &session_key);
+
+ if (sinfo.ssi_cipwd)
+ kmem_free(sinfo.ssi_cipwd, sinfo.ssi_cipwlen + 1);
+
+ if (auth_res == SMB_AUTH_FAILED) {
+ if (sinfo.ssi_cspwd)
+ kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
+ return (SDRC_ERROR);
+ }
+
+ sr->session->capabilities = sinfo.ssi_capabilities;
/*
* Check to see if SMB signing is enable, but if it is already turned
@@ -543,18 +415,19 @@
(sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) &&
(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
session_key)
- smb_sign_init(sr, session_key, (char *)cs_password, cs_pwlen);
+ smb_sign_init(sr, session_key, (char *)sinfo.ssi_cspwd,
+ sinfo.ssi_cspwlen);
- if (cs_password)
- kmem_free(cs_password, cs_pwlen + 1);
+ if (sinfo.ssi_cspwd)
+ kmem_free(sinfo.ssi_cspwd, sinfo.ssi_cspwlen + 1);
if (session_key)
kmem_free(session_key, sizeof (smb_session_key_t));
if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
(sr->sr_cfg->skc_signing_required)) {
- (void) inet_ntop(AF_INET, (char *)&sr->session->ipaddr,
- ipaddr_buf, sizeof (ipaddr_buf));
+ (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
+ SMB_IPSTRLEN(sr->session->ipaddr.a_family));
cmn_err(CE_NOTE,
"SmbSessonSetupX: client %s is not capable of signing",
ipaddr_buf);
@@ -580,12 +453,172 @@
3,
sr->andx_com,
-1, /* andx_off */
- ((user->u_flags & SMB_USER_FLAG_GUEST) ? 1 : 0),
+ (auth_res == SMB_AUTH_GUEST) ? 1 : 0,
VAR_BCC,
sr,
"Windows NT 4.0",
"NT LAN Manager 4.0",
- nbdomain);
+ sr->sr_cfg->skc_nbdomain);
return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
+
+/*
+ * Tries to authenticate the connected user.
+ *
+ * It first tries to see if the user has already been authenticated.
+ * If a match is found, the user structure in the session is duplicated
+ * and the function returns. Otherwise, user information is passed to
+ * smbd for authentication. If smbd can authenticate the user an access
+ * token structure is returned. A cred_t and user structure is created
+ * based on the returned access token.
+ */
+static int
+smb_authenticate(smb_request_t *sr, smb_sessionsetup_info_t *sinfo,
+ smb_session_key_t **session_key)
+{
+ char *hostname = sr->sr_cfg->skc_hostname;
+ int security = sr->sr_cfg->skc_secmode;
+ smb_token_t *usr_token = NULL;
+ smb_user_t *user = NULL;
+ netr_client_t clnt_info;
+ boolean_t need_lookup = B_FALSE;
+ uint32_t privileges;
+ cred_t *cr;
+ char *buf;
+ size_t buflen = 0;
+ char *p;
+
+ bzero(&clnt_info, sizeof (netr_client_t));
+
+ /*
+ * Handle user@domain format.
+ *
+ * We need to extract the user and domain names but
+ * should keep the request data as is. This is important
+ * for some forms of authentication.
+ */
+ clnt_info.real_username = sinfo->ssi_user;
+ clnt_info.real_domain = sinfo->ssi_domain;
+
+ if (*sinfo->ssi_domain == '\0') {
+ buflen = strlen(sinfo->ssi_user) + 1;
+ buf = smb_kstrdup(sinfo->ssi_user, buflen);
+ if ((p = strchr(buf, '@')) != NULL) {
+ *p = '\0';
+ clnt_info.real_username = buf;
+ clnt_info.real_domain = p + 1;
+ }
+ }
+
+ /*
+ * See if this user has already been authenticated.
+ *
+ * If no domain name is provided we cannot determine whether
+ * this is a local or domain user when server is operating
+ * in domain mode, so lookup will be done after authentication.
+ */
+ if (security == SMB_SECMODE_WORKGRP) {
+ user = smb_session_dup_user(sr->session, hostname,
+ clnt_info.real_username);
+ } else if (*clnt_info.real_domain != '\0') {
+ user = smb_session_dup_user(sr->session, clnt_info.real_domain,
+ clnt_info.real_username);
+ } else {
+ need_lookup = B_TRUE;
+ }
+
+ if (user != NULL) {
+ sr->user_cr = user->u_cred;
+ sr->smb_uid = user->u_uid;
+ sr->uid_user = user;
+
+ if (buflen != 0)
+ kmem_free(buf, buflen);
+
+ return ((user->u_flags & SMB_USER_FLAG_GUEST)
+ ? SMB_AUTH_GUEST : SMB_AUTH_USER);
+ }
+
+ clnt_info.logon_level = NETR_NETWORK_LOGON;
+ clnt_info.domain = sinfo->ssi_domain;
+ clnt_info.username = sinfo->ssi_user;
+ clnt_info.workstation = sr->session->workstation;
+ clnt_info.ipaddr = sr->session->ipaddr;
+ clnt_info.local_ipaddr = sr->session->local_ipaddr;
+ clnt_info.challenge_key.challenge_key_val =
+ sr->session->challenge_key;
+ clnt_info.challenge_key.challenge_key_len =
+ sr->session->challenge_len;
+ clnt_info.nt_password.nt_password_val = sinfo->ssi_cspwd;
+ clnt_info.nt_password.nt_password_len = sinfo->ssi_cspwlen;
+ clnt_info.lm_password.lm_password_val = sinfo->ssi_cipwd;
+ clnt_info.lm_password.lm_password_len = sinfo->ssi_cipwlen;
+ clnt_info.native_os = sr->session->native_os;
+ clnt_info.native_lm = smbnative_lm_value(sinfo->ssi_native_lm);
+ clnt_info.local_port = sr->session->s_local_port;
+
+ DTRACE_PROBE1(smb__sessionsetup__clntinfo, netr_client_t *,
+ &clnt_info);
+
+ usr_token = smb_get_token(&clnt_info);
+
+ if (buflen != 0)
+ kmem_free(buf, buflen);
+
+ if (usr_token == NULL) {
+ smbsr_error(sr, 0, ERRSRV, ERRbadpw);
+ return (SMB_AUTH_FAILED);
+ }
+
+ if (need_lookup) {
+ user = smb_session_dup_user(sr->session,
+ usr_token->tkn_domain_name, usr_token->tkn_account_name);
+
+ if (user != NULL) {
+ sr->user_cr = user->u_cred;
+ sr->smb_uid = user->u_uid;
+ sr->uid_user = user;
+
+ smb_token_free(usr_token);
+ return ((user->u_flags & SMB_USER_FLAG_GUEST)
+ ? SMB_AUTH_GUEST : SMB_AUTH_USER);
+ }
+ }
+
+ if (usr_token->tkn_session_key) {
+ *session_key = kmem_alloc(sizeof (smb_session_key_t),
+ KM_SLEEP);
+ (void) memcpy(*session_key, usr_token->tkn_session_key,
+ sizeof (smb_session_key_t));
+ }
+
+ if ((cr = smb_cred_create(usr_token, &privileges)) != NULL) {
+ user = smb_user_login(sr->session, cr,
+ usr_token->tkn_domain_name,
+ usr_token->tkn_account_name,
+ usr_token->tkn_flags,
+ privileges,
+ usr_token->tkn_audit_sid);
+
+ smb_cred_rele(user->u_cred);
+ if (user->u_privcred)
+ smb_cred_rele(user->u_privcred);
+ }
+
+ smb_token_free(usr_token);
+
+ if (user == NULL) {
+ if (*session_key)
+ kmem_free(*session_key, sizeof (smb_session_key_t));
+ smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
+ return (SMB_AUTH_FAILED);
+ }
+
+ sr->user_cr = user->u_cred;
+ sr->smb_uid = user->u_uid;
+ sr->uid_user = user;
+
+ return ((user->u_flags & SMB_USER_FLAG_GUEST)
+ ? SMB_AUTH_GUEST : SMB_AUTH_USER);
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c Sun Feb 01 19:44:54 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.
*/
@@ -204,47 +204,20 @@
#include <smbsrv/smb_incl.h>
#include <smbsrv/msgbuf.h>
-#include <smbsrv/smbtrans.h>
#include <smbsrv/smb_fsops.h>
-static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t);
-
-int smb_trans2_find_get_dents(smb_request_t *, smb_xa_t *,
- uint16_t, uint16_t, int, smb_node_t *,
- uint16_t, uint16_t, int, char *, uint32_t *, int *, int *);
-
-int smb_gather_dents_info(char *, ino_t, int, char *, uint32_t, int32_t *,
- smb_attr_t *, smb_node_t *, char *, char *);
-
-int smb_trans2_find_process_ients(smb_request_t *, smb_xa_t *,
- smb_dent_info_hdr_t *, uint16_t, uint16_t, int,
- smb_node_t *, int *, uint32_t *);
-
-int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *,
- smb_dent_info_t *, int, uint16_t, uint16_t,
- uint32_t, smb_node_t *, smb_node_t *);
+typedef struct smb_find_args {
+ uint16_t fa_infolev;
+ uint16_t fa_maxcount;
+ uint16_t fa_fflag;
+ uint32_t fa_maxdata;
+} smb_find_args_t;
-/*
- * The UNIX characters below are considered illegal in Windows file names.
- * The following character conversions are used to support sites in which
- * Catia v4 is in use on UNIX and Catia v5 is in use on Windows.
- *
- * ---------------------------
- * Unix-char | Windows-char
- * ---------------------------
- * " | (0x00a8) Diaeresis
- * * | (0x00a4) Currency Sign
- * : | (0x00f7) Division Sign
- * < | (0x00ab) Left-Pointing Double Angle Quotation Mark
- * > | (0x00bb) Right-Pointing Double Angle Quotation Mark
- * ? | (0x00bf) Inverted Question mark
- * \ | (0x00ff) Latin Small Letter Y with Diaeresis
- * | | (0x00a6) Broken Bar
- */
-static int (*catia_callback)(uint8_t *, uint8_t *, int) = NULL;
-void smb_register_catia_callback(
- int (*catia_v4tov5)(uint8_t *, uint8_t *, int));
-void smb_unregister_catia_callback();
+static int smb_trans2_find_entries(smb_request_t *, smb_xa_t *,
+ smb_odir_t *, smb_find_args_t *, boolean_t *);
+static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t);
+static int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *,
+ smb_fileinfo_t *, smb_find_args_t *);
/*
* Tunable parameter to limit the maximum
@@ -253,32 +226,6 @@
uint16_t smb_trans2_find_max = 128;
/*
- * smb_register_catia_callback
- *
- * This function will be invoked by the catia module to register its
- * function that translates filename in version 4 to a format that is
- * compatible to version 5.
- */
-void
-smb_register_catia_callback(
- int (*catia_v4tov5)(uint8_t *, uint8_t *, int))
-{
- catia_callback = catia_v4tov5;
-}
-
-/*
- * smb_unregister_catia_callback
- *
- * This function will unregister the catia callback prior to the catia
- * module gets unloaded.
- */
-void
-smb_unregister_catia_callback()
-{
- catia_callback = 0;
-}
-
-/*
* smb_com_trans2_find_first2
*
* Client Request Value
@@ -324,16 +271,14 @@
smb_sdrc_t
smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
{
- int more = 0, rc;
- uint16_t sattr, fflag, infolev;
- uint16_t maxcount = 0;
- int maxdata;
- int count, wildcards;
- uint32_t cookie;
+ int count;
+ uint16_t sattr, odid;
char *path;
- smb_node_t *dir_snode;
- char *pattern;
- uint16_t sid;
+ smb_odir_t *od;
+ smb_find_args_t args;
+ boolean_t eos;
+
+ bzero(&args, sizeof (smb_find_args_t));
if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
@@ -341,94 +286,57 @@
return (SDRC_ERROR);
}
- if (smb_mbc_decodef(&xa->req_param_mb, "%wwww4.u", sr,
- &sattr, &maxcount, &fflag, &infolev, &path) != 0) {
+ if (smb_mbc_decodef(&xa->req_param_mb, "%wwww4.u", sr, &sattr,
+ &args.fa_maxcount, &args.fa_fflag, &args.fa_infolev, &path) != 0) {
return (SDRC_ERROR);
}
- /*
- * stream files not allowed
- */
if (smb_is_stream_name(path)) {
smbsr_error(sr, NT_STATUS_OBJECT_NAME_INVALID,
ERRDOS, ERROR_INVALID_NAME);
return (SDRC_ERROR);
}
- if (fflag & SMB_FIND_WITH_BACKUP_INTENT)
+ if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT)
sr->user_cr = smb_user_getprivcred(sr->uid_user);
- maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag);
- if (maxdata == 0) {
- smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
- ERRDOS, ERROR_INVALID_LEVEL);
+ args.fa_maxdata =
+ smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag);
+ if (args.fa_maxdata == 0)
return (SDRC_ERROR);
- }
-
- /*
- * When maxcount is zero Windows behaves as if it was 1.
- */
- if (maxcount == 0)
- maxcount = 1;
-
- if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max))
- maxcount = smb_trans2_find_max;
if (sr->smb_flg2 & SMB_FLAGS2_UNICODE)
(void) smb_convert_unicode_wildcards(path);
- if (smb_rdir_open(sr, path, sattr) != 0)
+ odid = smb_odir_open(sr, path, sattr);
+ if (odid == 0)
return (SDRC_ERROR);
- /*
- * Get a copy of information
- */
- dir_snode = sr->sid_odir->d_dir_snode;
- pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP);
- (void) strcpy(pattern, sr->sid_odir->d_pattern);
-
- if (strcmp(pattern, "*.*") == 0)
- (void) strncpy(pattern, "*", sizeof (pattern));
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL)
+ return (SDRC_ERROR);
+ count = smb_trans2_find_entries(sr, xa, od, &args, &eos);
+ smb_odir_release(od);
- wildcards = sr->sid_odir->d_wildcards;
- sattr = sr->sid_odir->d_sattr;
- cookie = 0;
-
- rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata,
- dir_snode, sattr, maxcount, wildcards,
- pattern, &cookie, &more, &count);
-
- if (!count)
- rc = ENOENT;
-
- if (rc) {
- smb_rdir_close(sr);
- kmem_free(pattern, MAXNAMELEN);
- smbsr_errno(sr, rc);
+ if (count == -1) {
+ smb_odir_close(od);
return (SDRC_ERROR);
}
- /*
- * Save the sid here in case the search is closed below,
- * which will invalidate sr->smb_sid. We return the
- * sid, even though the search has been closed, to be
- * compatible with Windows.
- */
- sid = sr->smb_sid;
-
- if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST ||
- (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) {
- smb_rdir_close(sr);
- } else {
- mutex_enter(&sr->sid_odir->d_mutex);
- sr->sid_odir->d_cookie = cookie;
- mutex_exit(&sr->sid_odir->d_mutex);
+ if (count == 0) {
+ smb_odir_close(od);
+ smbsr_errno(sr, ENOENT);
+ return (SDRC_ERROR);
}
+ if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) ||
+ (eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
+ smb_odir_close(od);
+ } /* else leave odir open for trans2_find_next2 */
+
(void) smb_mbc_encodef(&xa->rep_param_mb, "wwwww",
- sid, count, (more ? 0 : 1), 0, 0);
+ odid, count, (eos) ? 1 : 0, 0, 0);
- kmem_free(pattern, MAXNAMELEN);
return (SDRC_SUCCESS);
}
@@ -486,10 +394,10 @@
* null-terminated unicode string.
*
* smb_mbc_decodef(&xa->req_param_mb, "%www lwu", sr,
- * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &fname)
+ * &odid, &fa_maxcount, &fa_infolev, &cookie, &fa_fflag, &fname)
*
- * The filename parameter is not currently decoded because we a
- * expect 2-byte null but Mac OS 10 clients send a 1-byte null,
+ * The filename parameter is not currently decoded because we
+ * expect a 2-byte null but Mac OS 10 clients send a 1-byte null,
* which leads to a decode error.
* Thus, we do not support resume by filename. We treat a request
* to resume by filename as SMB_FIND_CONTINUE_FROM_LAST.
@@ -497,88 +405,118 @@
smb_sdrc_t
smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
{
- uint16_t fflag, infolev;
- int maxdata, count, wildcards, more = 0, rc;
- uint32_t cookie;
- uint16_t maxcount = 0;
- smb_node_t *dir_snode;
- char *pattern;
- uint16_t sattr;
+ int count;
+ uint16_t odid;
+ uint32_t cookie;
+ smb_odir_t *od;
+ smb_find_args_t args;
+ boolean_t eos;
+ smb_odir_resume_t odir_resume;
- if (smb_mbc_decodef(&xa->req_param_mb, "%wwwlw", sr,
- &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag) != 0) {
+ bzero(&args, sizeof (smb_find_args_t));
+
+ if (smb_mbc_decodef(&xa->req_param_mb, "%wwwlw", sr, &odid,
+ &args.fa_maxcount, &args.fa_infolev, &cookie, &args.fa_fflag)
+ != 0) {
return (SDRC_ERROR);
}
/* continuation by filename not supported */
- if (cookie == 0)
- fflag |= SMB_FIND_CONTINUE_FROM_LAST;
+ if ((args.fa_fflag & SMB_FIND_CONTINUE_FROM_LAST) || (cookie == 0)) {
+ odir_resume.or_type = SMB_ODIR_RESUME_IDX;
+ odir_resume.or_idx = 0;
+ } else {
+ odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
+ odir_resume.or_cookie = cookie;
+ }
- if (fflag & SMB_FIND_WITH_BACKUP_INTENT)
+ if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT)
sr->user_cr = smb_user_getprivcred(sr->uid_user);
- sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid);
- if (sr->sid_odir == NULL) {
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
+ args.fa_maxdata =
+ smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag);
+ if (args.fa_maxdata == 0)
+ return (SDRC_ERROR);
+
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
+ return (SDRC_ERROR);
+ }
+ smb_odir_resume_at(od, &odir_resume);
+ count = smb_trans2_find_entries(sr, xa, od, &args, &eos);
+ smb_odir_release(od);
+
+ if (count == -1) {
+ smb_odir_close(od);
return (SDRC_ERROR);
}
- maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag);
- if (maxdata == 0) {
- smb_rdir_close(sr);
- smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
- ERRDOS, ERROR_INVALID_LEVEL);
- return (SDRC_ERROR);
- }
+ if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) ||
+ (eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
+ smb_odir_close(od);
+ } /* else leave odir open for trans2_find_next2 */
+
+ (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
+ count, (eos) ? 1 : 0, 0, 0);
+
+ return (SDRC_SUCCESS);
+}
+
- /*
- * When maxcount is zero Windows behaves as if it was 1.
- */
- if (maxcount == 0)
+/*
+ * smb_trans2_find_entries
+ *
+ * Find and encode up to args->fa_maxcount directory entries.
+ * For compatibilty with Windows, if args->fa_maxcount is zero treat it as 1.
+ *
+ * Returns:
+ * count - count of entries encoded
+ * *eos = B_TRUE if no more directory entries
+ * -1 - error
+ */
+static int
+smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
+ smb_find_args_t *args, boolean_t *eos)
+{
+ int rc;
+ uint16_t count, maxcount;
+ uint32_t cookie;
+ smb_fileinfo_t fileinfo;
+
+ if ((maxcount = args->fa_maxcount) == 0)
maxcount = 1;
if ((smb_trans2_find_max != 0) && (maxcount > smb_trans2_find_max))
maxcount = smb_trans2_find_max;
- /*
- * Get a copy of information
- */
- dir_snode = sr->sid_odir->d_dir_snode;
- pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP);
- (void) strcpy(pattern, sr->sid_odir->d_pattern);
- wildcards = sr->sid_odir->d_wildcards;
- sattr = sr->sid_odir->d_sattr;
- if (fflag & SMB_FIND_CONTINUE_FROM_LAST) {
- mutex_enter(&sr->sid_odir->d_mutex);
- cookie = sr->sid_odir->d_cookie;
- mutex_exit(&sr->sid_odir->d_mutex);
+ count = 0;
+ while (count < maxcount) {
+ if (smb_odir_read_fileinfo(sr, od, &fileinfo, eos) != 0)
+ return (-1);
+ if (*eos == B_TRUE)
+ break;
+
+ rc = smb_trans2_find_mbc_encode(sr, xa, &fileinfo, args);
+ if (rc == -1)
+ return (-1);
+ if (rc == 1)
+ break;
+
+ cookie = fileinfo.fi_cookie;
+ ++count;
}
- rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata,
- dir_snode, sattr, maxcount, wildcards, pattern, &cookie,
- &more, &count);
-
- if (rc) {
- smb_rdir_close(sr);
- kmem_free(pattern, MAXNAMELEN);
- smbsr_errno(sr, rc);
- return (SDRC_ERROR);
- }
+ /* save the last cookie returned to client */
+ if (count != 0)
+ smb_odir_save_cookie(od, 0, cookie);
- if (fflag & SMB_FIND_CLOSE_AFTER_REQUEST ||
- (!more && fflag & SMB_FIND_CLOSE_AT_EOS))
- smb_rdir_close(sr);
- else {
- mutex_enter(&sr->sid_odir->d_mutex);
- sr->sid_odir->d_cookie = cookie;
- mutex_exit(&sr->sid_odir->d_mutex);
- }
+ /* if eos not already detected, check if more entries */
+ if (!*eos)
+ (void) smb_odir_read_fileinfo(sr, od, &fileinfo, eos);
- (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
- count, (more ? 0 : 1), 0, 0);
-
- kmem_free(pattern, MAXNAMELEN);
- return (SDRC_SUCCESS);
+ return (count);
}
/*
@@ -642,341 +580,15 @@
default:
maxdata = 0;
+ smbsr_error(sr, NT_STATUS_INVALID_LEVEL,
+ ERRDOS, ERROR_INVALID_LEVEL);
}
return (maxdata);
}
/*
- * smb_trans2_find_get_dents
- *
- * This function will get all the directory entry information and mbc
- * encode it in the xa. If there is an error, it will be returned;
- * otherwise, 0 is returned.
- *
- * The more field will be updated. If the value returned is one, it means
- * there are more entries; otherwise, the returned value will be zero. The
- * cookie will also be updated to indicate the next start point for the
- * search. The count value will also be updated to stores the total entries
- * encoded.
- */
-int smb_trans2_find_get_dents(
- smb_request_t *sr,
- smb_xa_t *xa,
- uint16_t fflag,
- uint16_t infolev,
- int maxdata,
- smb_node_t *dir_snode,
- uint16_t sattr,
- uint16_t maxcount,
- int wildcards,
- char *pattern,
- uint32_t *cookie,
- int *more,
- int *count)
-{
- smb_dent_info_hdr_t *ihdr;
- smb_dent_info_t *ient;
- int dent_buf_size;
- int i;
- int total;
- int maxentries;
- int rc;
-
- ihdr = kmem_zalloc(sizeof (smb_dent_info_hdr_t), KM_SLEEP);
- *count = 0;
-
- if (!wildcards)
- maxentries = maxcount = 1;
- else {
- maxentries = (xa->rep_data_mb.max_bytes -
- xa->rep_data_mb.chain_offset) / maxdata;
- if (maxcount > SMB_MAX_DENTS_IOVEC)
- maxcount = SMB_MAX_DENTS_IOVEC;
- if (maxentries > maxcount)
- maxentries = maxcount;
- }
-
- /* Each entry will need to be aligned so add _POINTER_ALIGNMENT */
- dent_buf_size =
- maxentries * (SMB_MAX_DENT_INFO_SIZE + _POINTER_ALIGNMENT);
- ihdr->iov->iov_base = kmem_alloc(dent_buf_size, KM_SLEEP);
-
- ihdr->sattr = sattr;
- ihdr->pattern = pattern;
- ihdr->sr = sr;
-
- ihdr->uio.uio_iovcnt = maxcount;
- ihdr->uio.uio_resid = dent_buf_size;
- ihdr->uio.uio_iov = ihdr->iov;
- ihdr->uio.uio_loffset = 0;
-
- rc = smb_get_dents(sr, cookie, dir_snode, wildcards, ihdr, more);
- if (rc != 0) {
- goto out;
- }
-
- if (ihdr->iov->iov_len == 0)
- *count = 0;
- else
- *count = smb_trans2_find_process_ients(sr, xa, ihdr, fflag,
- infolev, maxdata, dir_snode, more, cookie);
- rc = 0;
-
-out:
-
- total = maxcount - ihdr->uio.uio_iovcnt;
- ASSERT((total >= 0) && (total <= SMB_MAX_DENTS_IOVEC));
- for (i = 0; i < total; i++) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ient = (smb_dent_info_t *)ihdr->iov[i].iov_base;
- ASSERT(ient);
- smb_node_release(ient->snode);
- }
-
- kmem_free(ihdr->iov->iov_base, dent_buf_size);
- kmem_free(ihdr, sizeof (smb_dent_info_hdr_t));
- return (0);
-}
-
-
-/*
- * smb_get_dents
- *
- * This function utilizes "smb_fsop_getdents()" to get dir entries.
- * The "smb_gather_dents_info()" is the call back function called
- * inside the file system. It is very important that the function
- * does not sleep or yield since it is processed inside a file
- * system transaction.
- *
- * The function returns 0 when successful and error code when failed.
- * If more is provided, the return value of 1 is returned indicating
- * more entries; otherwise, 0 is returned.
- */
-int smb_get_dents(
- smb_request_t *sr,
- uint32_t *cookie,
- smb_node_t *dir_snode,
- uint32_t wildcards,
- smb_dent_info_hdr_t *ihdr,
- int *more)
-{
- int rc;
- char *namebuf;
- smb_node_t *snode;
- smb_attr_t file_attr;
- uint32_t maxcnt = ihdr->uio.uio_iovcnt;
- char shortname[SMB_SHORTNAMELEN], name83[SMB_SHORTNAMELEN];
-
- namebuf = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
- if (more)
- *more = 0;
-
- if (!wildcards) {
- /* Already found entry? */
- if (*cookie != 0)
- return (0);
- shortname[0] = '\0';
-
- rc = smb_fsop_lookup(sr, sr->user_cr, 0, sr->tid_tree->t_snode,
- dir_snode, ihdr->pattern, &snode, &file_attr, shortname,
- name83);
-
- if (rc) {
- kmem_free(namebuf, MAXNAMELEN);
- return (rc);
- }
-
- (void) strlcpy(namebuf, snode->od_name, MAXNAMELEN);
-
- /*
- * It is not necessary to set the "force" flag (i.e. to
- * take into account mangling for case-insensitive collisions)
- */
-
- if (shortname[0] == '\0')
- (void) smb_mangle_name(snode->attr.sa_vattr.va_nodeid,
- namebuf, shortname, name83, 0);
- (void) smb_gather_dents_info((char *)ihdr,
- snode->attr.sa_vattr.va_nodeid,
- strlen(namebuf), namebuf, -1, (int *)&maxcnt,
- &snode->attr, snode, shortname, name83);
- kmem_free(namebuf, MAXNAMELEN);
- return (0);
- }
-
- if ((rc = smb_fsop_getdents(sr, sr->user_cr, dir_snode, cookie,
- 0, (int *)&maxcnt, (char *)ihdr, ihdr->pattern)) != 0) {
- if (rc == ENOENT) {
- kmem_free(namebuf, MAXNAMELEN);
- return (0);
- }
- kmem_free(namebuf, MAXNAMELEN);
- return (rc);
- }
-
- if (*cookie != 0x7FFFFFFF && more)
- *more = 1;
-
- kmem_free(namebuf, MAXNAMELEN);
- return (0);
-}
-
-
-/*
- * smb_gather_dents_info
- *
- * The function will accept information of each directory entry and put
- * the needed information in the buffer. It is passed as the call back
- * function for smb_fsop_getdents() to gather trans2 find info.
- *
- * Only valid entry will be stored in the buffer.
- *
- * Returns: -1 - error, buffer too small
- * n - number of valid entries (0 or 1)
- */
-int /*ARGSUSED*/
-smb_gather_dents_info(
- char *args,
- ino_t fileid,
- int namelen,
- char *name,
- uint32_t cookie,
- int32_t *countp,
- smb_attr_t *attr,
- smb_node_t *snode,
- char *shortname,
- char *name83)
-{
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)args;
- smb_dent_info_t *ient;
- uint8_t *v5_name = NULL;
- uint8_t *np = (uint8_t *)name;
- int reclen = sizeof (smb_dent_info_t) + namelen;
-
- v5_name = kmem_alloc(MAXNAMELEN-1, KM_SLEEP);
-
- if (!ihdr->uio.uio_iovcnt || ihdr->uio.uio_resid < reclen) {
- kmem_free(v5_name, MAXNAMELEN-1);
- smb_node_release(snode);
- return (-1);
- }
-
- if (!smb_sattr_check(attr, name, ihdr->sattr)) {
- kmem_free(v5_name, MAXNAMELEN-1);
- smb_node_release(snode);
- return (0);
- }
-
- if (catia_callback) {
- catia_callback(v5_name, (uint8_t *)name, MAXNAMELEN-1);
- np = v5_name;
- reclen = sizeof (smb_dent_info_t) + strlen((char *)v5_name);
- }
-
- ASSERT(snode);
- ASSERT(snode->n_magic == SMB_NODE_MAGIC);
- ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
-
- /*
- * Each entry needs to be properly aligned or we may get an alignment
- * fault on sparc.
- */
- ihdr->uio.uio_loffset = (offset_t)PTRALIGN(ihdr->uio.uio_loffset);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ient = (smb_dent_info_t *)&ihdr->iov->iov_base[ihdr->uio.uio_loffset];
-
- ient->cookie = cookie;
- ient->attr = *attr;
- ient->snode = snode;
-
- (void) strcpy(ient->name, (char *)np);
- (void) strcpy(ient->shortname, shortname);
- (void) strcpy(ient->name83, name83);
- ihdr->uio.uio_iov->iov_base = (char *)ient;
- ihdr->uio.uio_iov->iov_len = reclen;
-
- ihdr->uio.uio_iov++;
- ihdr->uio.uio_iovcnt--;
- ihdr->uio.uio_resid -= reclen;
- ihdr->uio.uio_loffset += reclen;
-
- kmem_free(v5_name, MAXNAMELEN-1);
- return (1);
-}
-
-
-
-/*
- * smb_trans2_find_process_ients
- *
- * This function encodes the directory entry information store in
- * the iov structure of the ihdr structure.
- *
- * The total entries encoded will be returned. If the entries encoded
- * is less than the total entries in the iov, the more field will
- * be updated to 1. Also, the next cookie wil be updated as well.
- */
-int
-smb_trans2_find_process_ients(
- smb_request_t *sr,
- smb_xa_t *xa,
- smb_dent_info_hdr_t *ihdr,
- uint16_t fflag,
- uint16_t infolev,
- int maxdata,
- smb_node_t *dir_snode,
- int *more,
- uint32_t *cookie)
-{
- int i, err = 0;
- smb_dent_info_t *ient;
- uint32_t mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE)
- ? SMB_MSGBUF_UNICODE : 0;
-
- for (i = 0; i < SMB_MAX_DENTS_IOVEC; i++) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- if ((ient = (smb_dent_info_t *)ihdr->iov[i].iov_base) == 0)
- break;
-
- /*
- * Observed differences between our response and Windows
- * response, which hasn't caused a problem yet!
- *
- * 1. The NextEntryOffset field for the last entry should
- * be 0. This code always calculate the record length
- * and puts the result in the NextEntryOffset field.
- *
- * 2. The FileIndex field is always 0. This code puts
- * the cookie in the FileIndex field.
- */
- err = smb_trans2_find_mbc_encode(sr, xa, ient, maxdata, infolev,
- fflag, mb_flags, dir_snode, NULL);
-
- if (err)
- break;
- }
-
- /*
- * Not enough space to store all the entries returned,
- * which is indicated by setting more.
- */
- if (more && err < 0) {
- *more = 1;
-
- /*
- * Assume the space will be at least enough for 1 entry.
- */
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- ient = (smb_dent_info_t *)ihdr->iov[i-1].iov_base;
- *cookie = ient->cookie;
- }
- return (i);
-}
-
-/*
- * smb_trans2_find_mbc_encode
+ * smb_trans2_mbc_encode
*
* This function encodes the mbc for one directory entry.
*
@@ -991,41 +603,31 @@
* filename is ascii the name length returned to the client should
* include the null terminator. Otherwise the length returned to
* the client should not include the terminator.
+ *
+ * Returns: 0 - data successfully encoded
+ * 1 - client request's maxdata limit reached
+ * -1 - error
*/
-int /*ARGSUSED*/
-smb_trans2_find_mbc_encode(
- smb_request_t *sr,
- smb_xa_t *xa,
- smb_dent_info_t *ient,
- int maxdata,
- uint16_t infolev,
- uint16_t fflag,
- uint32_t mb_flags,
- smb_node_t *dir_snode,
- smb_node_t *sd_snode)
+static int
+smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
+ smb_fileinfo_t *fileinfo, smb_find_args_t *args)
{
- int namelen, shortlen, buflen;
- uint32_t next_entry_offset;
- char buf83[26];
- char *tmpbuf;
- smb_msgbuf_t mb;
- uint32_t dattr = 0;
- uint32_t dsize32 = 0;
- uint32_t asize32 = 0;
- u_offset_t datasz = 0;
- u_offset_t allocsz = 0;
- smb_node_t *lnk_snode;
- smb_attr_t lnkattr;
- int rc;
+ int namelen, shortlen, buflen;
+ uint32_t next_entry_offset;
+ uint32_t dsize32, asize32;
+ uint32_t mb_flags = 0;
+ char buf83[26];
+ char *tmpbuf;
+ smb_msgbuf_t mb;
- namelen = smb_ascii_or_unicode_strlen(sr, ient->name);
+ namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name);
if (namelen == -1)
- return (1);
+ return (-1);
- next_entry_offset = maxdata + namelen;
+ next_entry_offset = args->fa_maxdata + namelen;
- if (MBC_ROOM_FOR(&xa->rep_data_mb, (maxdata + namelen)) == 0)
- return (-1);
+ if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
+ return (1);
/*
* If ascii the filename length returned to the client should
@@ -1033,77 +635,38 @@
* EASIZE.
*/
if (!(sr->smb_flg2 & SMB_FLAGS2_UNICODE)) {
- if ((infolev != SMB_INFO_STANDARD) &&
- (infolev != SMB_INFO_QUERY_EA_SIZE))
+ if ((args->fa_infolev != SMB_INFO_STANDARD) &&
+ (args->fa_infolev != SMB_INFO_QUERY_EA_SIZE))
namelen += 1;
}
- if (ient->attr.sa_vattr.va_type == VLNK) {
- rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
- sr->tid_tree->t_snode, dir_snode, ient->name, &lnk_snode,
- &lnkattr, 0, 0);
+ mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0;
+ dsize32 = (fileinfo->fi_size > UINT_MAX) ?
+ UINT_MAX : (uint32_t)fileinfo->fi_size;
+ asize32 = (fileinfo->fi_alloc_size > UINT_MAX) ?
+ UINT_MAX : (uint32_t)fileinfo->fi_alloc_size;
- /*
- * We normally want to resolve the object to which a symlink
- * refers so that CIFS clients can access sub-directories and
- * find the correct association for files. This causes a
- * problem, however, if a symlink in a sub-directory points
- * to a parent directory (some UNIX GUI's create a symlink in
- * $HOME/.desktop that points to the user's home directory).
- * Some Windows applications (i.e. virus scanning) loop/hang
- * trying to follow this recursive path and there is little
- * we can do because the path is constructed on the client.
- * skc_dirsymlink_enable allows an end-user to disable
- * symlinks to directories. Symlinks to other object types
- * should be unaffected.
- */
- if (rc == 0) {
- if (smb_dirsymlink_enable ||
- (lnkattr.sa_vattr.va_type != VDIR)) {
- smb_node_release(ient->snode);
- ient->snode = lnk_snode;
- ient->attr = lnkattr;
- } else {
- smb_node_release(lnk_snode);
- }
- }
- }
-
- if (infolev != SMB_FIND_FILE_NAMES_INFO) {
- /* data size */
- datasz = smb_node_get_size(ient->snode, &ient->attr);
- dsize32 = (datasz > UINT_MAX) ? UINT_MAX : (uint32_t)datasz;
-
- /* allocation size */
- allocsz = ient->attr.sa_vattr.va_nblocks * DEV_BSIZE;
- asize32 = (allocsz > UINT_MAX) ? UINT_MAX : (uint32_t)allocsz;
-
- dattr = smb_node_get_dosattr(ient->snode);
- }
-
- switch (infolev) {
+ switch (args->fa_infolev) {
case SMB_INFO_STANDARD:
- if (fflag & SMB_FIND_RETURN_RESUME_KEYS)
+ if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
- ient->cookie);
+ fileinfo->fi_cookie);
(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwbu", sr,
- ient->attr.sa_crtime.tv_sec ?
- smb_gmt2local(sr, ient->attr.sa_crtime.tv_sec) :
- smb_gmt2local(sr, ient->attr.sa_vattr.va_mtime.tv_sec),
- smb_gmt2local(sr, ient->attr.sa_vattr.va_atime.tv_sec),
- smb_gmt2local(sr, ient->attr.sa_vattr.va_mtime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_crtime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_atime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_mtime.tv_sec),
dsize32,
asize32,
- dattr,
+ fileinfo->fi_dosattr,
namelen,
- ient->name);
+ fileinfo->fi_name);
break;
case SMB_INFO_QUERY_EA_SIZE:
- if (fflag & SMB_FIND_RETURN_RESUME_KEYS)
+ if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
- ient->cookie);
+ fileinfo->fi_cookie);
/*
* Unicode filename should NOT be aligned. Encode ('u')
@@ -1115,7 +678,7 @@
buflen = namelen + sizeof (mts_wchar_t);
tmpbuf = kmem_zalloc(buflen, KM_SLEEP);
smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen, mb_flags);
- if (smb_msgbuf_encode(&mb, "u", ient->name) < 0) {
+ if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_name) < 0) {
smb_msgbuf_term(&mb);
kmem_free(tmpbuf, buflen);
return (-1);
@@ -1123,14 +686,12 @@
tmpbuf[namelen] = '\0';
(void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb#c", sr,
- ient->attr.sa_crtime.tv_sec ?
- smb_gmt2local(sr, ient->attr.sa_crtime.tv_sec) :
- smb_gmt2local(sr, ient->attr.sa_vattr.va_mtime.tv_sec),
- smb_gmt2local(sr, ient->attr.sa_vattr.va_atime.tv_sec),
- smb_gmt2local(sr, ient->attr.sa_vattr.va_mtime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_crtime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_atime.tv_sec),
+ smb_gmt2local(sr, fileinfo->fi_mtime.tv_sec),
dsize32,
asize32,
- dattr,
+ fileinfo->fi_dosattr,
0L, /* EA Size */
namelen,
namelen + 1,
@@ -1143,81 +704,77 @@
case SMB_FIND_FILE_DIRECTORY_INFO:
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqllu", sr,
next_entry_offset,
- ient->cookie,
- ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime :
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_atime,
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_ctime,
- (uint64_t)datasz,
- (uint64_t)allocsz,
- dattr,
+ fileinfo->fi_cookie,
+ &fileinfo->fi_crtime,
+ &fileinfo->fi_atime,
+ &fileinfo->fi_mtime,
+ &fileinfo->fi_ctime,
+ fileinfo->fi_size,
+ fileinfo->fi_alloc_size,
+ fileinfo->fi_dosattr,
namelen,
- ient->name);
+ fileinfo->fi_name);
break;
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllu", sr,
next_entry_offset,
- ient->cookie,
- ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime :
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_atime,
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_ctime,
- (uint64_t)datasz,
- (uint64_t)allocsz,
- dattr,
+ fileinfo->fi_cookie,
+ &fileinfo->fi_crtime,
+ &fileinfo->fi_atime,
+ &fileinfo->fi_mtime,
+ &fileinfo->fi_ctime,
+ fileinfo->fi_size,
+ fileinfo->fi_alloc_size,
+ fileinfo->fi_dosattr,
namelen,
0L,
- ient->name);
+ fileinfo->fi_name);
break;
case SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO:
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll4.qu", sr,
next_entry_offset,
- ient->cookie,
- ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime :
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_atime,
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_ctime,
- (uint64_t)datasz,
- (uint64_t)allocsz,
- dattr,
+ fileinfo->fi_cookie,
+ &fileinfo->fi_crtime,
+ &fileinfo->fi_atime,
+ &fileinfo->fi_mtime,
+ &fileinfo->fi_ctime,
+ fileinfo->fi_size,
+ fileinfo->fi_alloc_size,
+ fileinfo->fi_dosattr,
namelen,
0L,
- ient->attr.sa_vattr.va_nodeid,
- ient->name);
+ fileinfo->fi_nodeid,
+ fileinfo->fi_name);
break;
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
bzero(buf83, sizeof (buf83));
smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
mb_flags);
- if (smb_msgbuf_encode(&mb, "U", ient->shortname) < 0) {
+ if (smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname) < 0) {
smb_msgbuf_term(&mb);
return (-1);
}
- shortlen = mts_wcequiv_strlen(ient->shortname);
+ shortlen = mts_wcequiv_strlen(fileinfo->fi_shortname);
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllb.24cu",
sr,
next_entry_offset,
- ient->cookie,
- ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime :
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_atime,
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_ctime,
- (uint64_t)datasz,
- (uint64_t)allocsz,
- dattr,
+ fileinfo->fi_cookie,
+ &fileinfo->fi_crtime,
+ &fileinfo->fi_atime,
+ &fileinfo->fi_mtime,
+ &fileinfo->fi_ctime,
+ fileinfo->fi_size,
+ fileinfo->fi_alloc_size,
+ fileinfo->fi_dosattr,
namelen,
0L,
shortlen,
buf83,
- ient->name);
+ fileinfo->fi_name);
smb_msgbuf_term(&mb);
break;
@@ -1226,31 +783,31 @@
bzero(buf83, sizeof (buf83));
smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83),
mb_flags);
- if (smb_msgbuf_encode(&mb, "u", ient->shortname) < 0) {
+ if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_shortname) < 0) {
smb_msgbuf_term(&mb);
return (-1);
}
- shortlen = smb_ascii_or_unicode_strlen(sr, ient->shortname);
+ shortlen = smb_ascii_or_unicode_strlen(sr,
+ fileinfo->fi_shortname);
(void) smb_mbc_encodef(&xa->rep_data_mb,
"%llTTTTqqlllb.24c2.qu",
sr,
next_entry_offset,
- ient->cookie,
- ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime :
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_atime,
- &ient->attr.sa_vattr.va_mtime,
- &ient->attr.sa_vattr.va_ctime,
- (uint64_t)datasz,
- (uint64_t)allocsz,
- dattr,
+ fileinfo->fi_cookie,
+ &fileinfo->fi_crtime,
+ &fileinfo->fi_atime,
+ &fileinfo->fi_mtime,
+ &fileinfo->fi_ctime,
+ fileinfo->fi_size,
+ fileinfo->fi_alloc_size,
+ fileinfo->fi_dosattr,
namelen,
0L,
shortlen,
buf83,
- ient->attr.sa_vattr.va_nodeid,
- ient->name);
+ fileinfo->fi_nodeid,
+ fileinfo->fi_name);
smb_msgbuf_term(&mb);
break;
@@ -1258,9 +815,9 @@
case SMB_FIND_FILE_NAMES_INFO:
(void) smb_mbc_encodef(&xa->rep_data_mb, "%lllu", sr,
next_entry_offset,
- ient->cookie,
+ fileinfo->fi_cookie,
namelen,
- ient->name);
+ fileinfo->fi_name);
break;
}
@@ -1273,12 +830,8 @@
smb_sdrc_t
smb_pre_find_close2(smb_request_t *sr)
{
- int rc;
-
- rc = smbsr_decode_vwv(sr, "w", &sr->smb_sid);
-
DTRACE_SMB_1(op__FindClose2__start, smb_request_t *, sr);
- return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
+ return (SDRC_SUCCESS);
}
void
@@ -1290,13 +843,21 @@
smb_sdrc_t
smb_com_find_close2(smb_request_t *sr)
{
- sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid);
- if (sr->sid_odir == NULL) {
- smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
+ uint16_t odid;
+ smb_odir_t *od;
+
+ if (smbsr_decode_vwv(sr, "w", &odid) != 0)
+ return (SDRC_ERROR);
+
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od == NULL) {
+ smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
+ ERRDOS, ERROR_INVALID_HANDLE);
return (SDRC_ERROR);
}
- smb_rdir_close(sr);
+ smb_odir_close(od);
+ smb_odir_release(od);
if (smbsr_encode_empty_result(sr))
return (SDRC_ERROR);
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c Sun Feb 01 19:44:54 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.
*/
@@ -428,13 +428,15 @@
* entries (smb_fsop_stream_readdir) it is treated as if there are
* no [more] directory entries. The entries that have been read so
* far are returned and no error is reported.
+ *
+ * Offset calculation:
+ * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
*/
-
void
smb_encode_stream_info(
struct smb_request *sr,
struct smb_xa *xa,
- struct smb_node *snode,
+ struct smb_node *fnode,
smb_attr_t *attr)
{
char *stream_name;
@@ -442,76 +444,59 @@
uint32_t stream_nlen;
uint32_t pad;
u_offset_t datasz;
- int is_dir;
- uint32_t cookie = 0;
- struct fs_stream_info *stream_info;
- struct fs_stream_info *stream_info_next;
+ boolean_t is_dir;
+ smb_streaminfo_t *sinfo, *sinfo_next;
int rc = 0;
- int done = 0;
+ boolean_t done = B_FALSE;
+ boolean_t eos = B_FALSE;
+ uint16_t odid;
+ smb_odir_t *od = NULL;
- stream_info = kmem_alloc(sizeof (struct fs_stream_info), KM_SLEEP);
- stream_info_next = kmem_alloc(sizeof (struct fs_stream_info), KM_SLEEP);
- is_dir = (attr->sa_vattr.va_type == VDIR) ? 1 : 0;
+ sinfo = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
+ sinfo_next = kmem_alloc(sizeof (smb_streaminfo_t), KM_SLEEP);
+ is_dir = (attr->sa_vattr.va_type == VDIR);
datasz = attr->sa_vattr.va_size;
- rc = smb_fsop_stream_readdir(sr, kcred, snode, &cookie, stream_info,
- NULL, NULL);
-
- if ((cookie == 0x7FFFFFFF) || (rc != 0)) {
- if (is_dir == 0) {
- stream_name = "::$DATA";
- stream_nlen =
- smb_ascii_or_unicode_strlen(sr, stream_name);
- next_offset = 0;
+ odid = smb_odir_openat(sr, fnode);
+ if (odid != 0)
+ od = smb_tree_lookup_odir(sr->tid_tree, odid);
+ if (od != NULL)
+ rc = smb_odir_read_streaminfo(sr, od, sinfo, &eos);
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu",
- sr, next_offset, stream_nlen, datasz, datasz,
- stream_name);
- }
- /* No named streams, we're done */
- kmem_free(stream_info, sizeof (struct fs_stream_info));
- kmem_free(stream_info_next, sizeof (struct fs_stream_info));
- return;
- }
+ if ((od == NULL) || (rc != 0) || (eos))
+ done = B_TRUE;
- if (is_dir == 0) {
+ /*
+ * If not a directory, encode an entry for the unnamed stream.
+ */
+ if (!is_dir) {
stream_name = "::$DATA";
stream_nlen = smb_ascii_or_unicode_strlen(sr, stream_name);
- /*
- * Offset calculation:
- * 2 dwords + 2 quadwords => 4 + 4 + 8 + 8 => 24
- */
- next_offset = 24 + stream_nlen +
- smb_ascii_or_unicode_null_len(sr);
+ if (done)
+ next_offset = 0;
+ else
+ next_offset = 24 + stream_nlen +
+ smb_ascii_or_unicode_null_len(sr);
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu", sr,
next_offset, stream_nlen, datasz, datasz, stream_name);
}
+ /*
+ * Since last packet does not have a pad we need to check
+ * for the next stream before we encode the current one
+ */
while (!done) {
- /*
- * Named streams.
- */
- stream_nlen = smb_ascii_or_unicode_strlen(sr,
- stream_info->name);
- next_offset = 0;
- pad = 0;
+ stream_nlen = smb_ascii_or_unicode_strlen(sr, sinfo->si_name);
+ sinfo_next->si_name[0] = 0;
- /*
- * this is a little kludgy, since we use a cookie now and last
- * packet does not have a pad we need to check the next item
- * before we encode the current one
- */
- stream_info_next->name[0] = 0;
- rc = smb_fsop_stream_readdir(sr, kcred, snode, &cookie,
- stream_info_next, NULL, NULL);
- if ((cookie == 0x7FFFFFFF) || (rc != 0)) {
- done = 1;
+ rc = smb_odir_read_streaminfo(sr, od, sinfo_next, &eos);
+ if ((rc != 0) || (eos)) {
+ done = B_TRUE;
+ next_offset = 0;
+ pad = 0;
} else {
- if (cookie == 0) {
- break;
- }
next_offset = 24 + stream_nlen +
smb_ascii_or_unicode_null_len(sr);
pad = smb_pad_align(next_offset, 8);
@@ -519,14 +504,18 @@
}
(void) smb_mbc_encodef(&xa->rep_data_mb, "%llqqu#.",
sr, next_offset, stream_nlen,
- stream_info->size, stream_info->size,
- stream_info->name, pad);
+ sinfo->si_size, sinfo->si_size,
+ sinfo->si_name, pad);
+
+ (void) memcpy(sinfo, sinfo_next, sizeof (smb_streaminfo_t));
+ }
- (void) memcpy(stream_info, stream_info_next,
- sizeof (struct fs_stream_info));
+ kmem_free(sinfo, sizeof (smb_streaminfo_t));
+ kmem_free(sinfo_next, sizeof (smb_streaminfo_t));
+ if (od) {
+ smb_odir_release(od);
+ smb_odir_close(od);
}
- kmem_free(stream_info, sizeof (struct fs_stream_info));
- kmem_free(stream_info_next, sizeof (struct fs_stream_info));
}
/*
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c Sun Feb 01 19:44:54 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.
*/
@@ -190,6 +190,8 @@
static void smb_tree_get_volname(vfs_t *, smb_tree_t *);
static void smb_tree_get_flags(vfs_t *, smb_tree_t *);
static void smb_tree_log(smb_request_t *, const char *, const char *, ...);
+static void smb_tree_close_odirs(smb_tree_t *, uint16_t);
+static smb_odir_t *smb_tree_get_odir(smb_tree_t *, smb_odir_t *);
/*
* Extract the share name and share type and connect as appropriate.
@@ -263,7 +265,7 @@
/*
* The directories opened under this tree are closed.
*/
- smb_odir_close_all(tree);
+ smb_tree_close_odirs(tree, 0);
mutex_enter(&tree->t_mutex);
tree->t_state = SMB_TREE_STATE_DISCONNECTED;
}
@@ -329,7 +331,7 @@
ASSERT(tree->t_magic == SMB_TREE_MAGIC);
smb_ofile_close_all_by_pid(tree, pid);
- smb_odir_close_all_by_pid(tree, pid);
+ smb_tree_close_odirs(tree, pid);
}
/*
@@ -377,7 +379,7 @@
si = kmem_zalloc(sizeof (smb_share_t), KM_SLEEP);
if (smb_kshare_getinfo(sr->sr_server->sv_lmshrd, (char *)sharename, si,
- sr->session->ipaddr) != NERR_Success) {
+ &sr->session->ipaddr) != NERR_Success) {
smb_tree_log(sr, sharename, "share not found");
smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
kmem_free(si, sizeof (smb_share_t));
@@ -532,7 +534,7 @@
return (NULL);
}
- if (smb_idpool_constructor(&tree->t_sid_pool)) {
+ if (smb_idpool_constructor(&tree->t_odid_pool)) {
smb_idpool_destructor(&tree->t_fid_pool);
smb_idpool_free(&user->u_tid_pool, tid);
kmem_cache_free(user->u_server->si_cache_tree, tree);
@@ -616,7 +618,7 @@
smb_llist_destructor(&tree->t_ofile_list);
smb_llist_destructor(&tree->t_odir_list);
smb_idpool_destructor(&tree->t_fid_pool);
- smb_idpool_destructor(&tree->t_sid_pool);
+ smb_idpool_destructor(&tree->t_odid_pool);
kmem_cache_free(tree->t_server->si_cache_tree, tree);
}
@@ -866,3 +868,105 @@
cmn_err(CE_NOTE, "smbd[%s\\%s]: %s %s",
user->u_domain, user->u_name, sharename, buf);
}
+
+/*
+ * smb_tree_lookup_odir
+ *
+ * Find the specified odir in the tree's list of odirs, and
+ * attempt to obtain a hold on the odir.
+ *
+ * Returns NULL if odir not found or a hold cannot be obtained.
+ */
+smb_odir_t *
+smb_tree_lookup_odir(smb_tree_t *tree, uint16_t odid)
+{
+ smb_odir_t *od;
+ smb_llist_t *od_list;
+
+ ASSERT(tree);
+ ASSERT(tree->t_magic == SMB_TREE_MAGIC);
+
+ od_list = &tree->t_odir_list;
+ smb_llist_enter(od_list, RW_READER);
+
+ od = smb_llist_head(od_list);
+ while (od) {
+ if (od->d_odid == odid) {
+ if (!smb_odir_hold(od))
+ od = NULL;
+ break;
+ }
+ od = smb_llist_next(od_list, od);
+ }
+
+ smb_llist_exit(od_list);
+ return (od);
+}
+
+/*
+ * smb_tree_get_odir
+ *
+ * Find the next open odir in the tree's list of odirs, and obtain
+ * a hold on it. (A hold can only be obtained on an open odir.)
+ * If the specified odir is NULL the search starts at the beginning
+ * of the tree's odir list, otherwise the search starts after the
+ * specified odir.
+ */
+static smb_odir_t *
+smb_tree_get_odir(smb_tree_t *tree, smb_odir_t *od)
+{
+ smb_llist_t *od_list;
+
+ ASSERT(tree);
+ ASSERT(tree->t_magic == SMB_TREE_MAGIC);
+
+ od_list = &tree->t_odir_list;
+ smb_llist_enter(od_list, RW_READER);
+
+ if (od) {
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ od = smb_llist_next(od_list, od);
+ } else {
+ od = smb_llist_head(od_list);
+ }
+
+ while (od) {
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+
+ if (smb_odir_hold(od))
+ break;
+ od = smb_llist_next(od_list, od);
+ }
+
+ smb_llist_exit(od_list);
+ return (od);
+}
+
+/*
+ * smb_tree_close_odirs
+ *
+ * Close all open odirs in the tree's list which were opened by
+ * the process identified by pid.
+ * If pid is zero, close all open odirs in the tree's list.
+ */
+static void
+smb_tree_close_odirs(smb_tree_t *tree, uint16_t pid)
+{
+ smb_odir_t *od, *next_od;
+
+ ASSERT(tree);
+ ASSERT(tree->t_magic == SMB_TREE_MAGIC);
+
+ od = smb_tree_get_odir(tree, NULL);
+ while (od) {
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+ ASSERT(od->d_tree == tree);
+
+ next_od = smb_tree_get_odir(tree, od);
+ if ((pid == 0) || (od->d_opened_by_pid == pid))
+ smb_odir_close(od);
+ smb_odir_release(od);
+
+ od = next_od;
+ }
+}
--- a/usr/src/uts/common/fs/smbsrv/smb_upcalls.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_upcalls.c Sun Feb 01 19:44:54 2009 -0700
@@ -63,7 +63,7 @@
}
smb_token_t *
-smb_upcall_get_token(netr_client_t *clnt_info)
+smb_get_token(netr_client_t *clnt_info)
{
char *arg, *rsp;
size_t arg_size, rsp_size;
--- a/usr/src/uts/common/fs/smbsrv/smb_util.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_util.c Sun Feb 01 19:44:54 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.
*/
@@ -96,19 +96,6 @@
}
int
-smb_component_match(
- struct smb_request *sr,
- ino64_t fileid,
- struct smb_odir *od,
- smb_odir_context_t *pc)
-{
- boolean_t ignore_case = SMB_TREE_IS_CASEINSENSITIVE(sr);
-
- return (smb_match_name(fileid, pc->dc_name, pc->dc_shortname,
- pc->dc_name83, od->d_pattern, ignore_case));
-}
-
-int
smb_convert_unicode_wildcards(char *path)
{
int wildcards = 0;
@@ -208,7 +195,7 @@
* Returns true if the file and sattr match; otherwise, returns false.
*/
boolean_t
-smb_sattr_check(smb_attr_t *ap, char *name, unsigned short sattr)
+smb_sattr_check(uint16_t dosattr, uint16_t sattr, char *name)
{
if (name) {
if (smb_is_dot_or_dotdot(name) &&
@@ -216,15 +203,15 @@
return (B_FALSE);
}
- if ((ap->sa_vattr.va_type == VDIR) &&
+ if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) &&
!(sattr & FILE_ATTRIBUTE_DIRECTORY))
return (B_FALSE);
- if ((ap->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) &&
+ if ((dosattr & FILE_ATTRIBUTE_HIDDEN) &&
!(sattr & FILE_ATTRIBUTE_HIDDEN))
return (B_FALSE);
- if ((ap->sa_dosattr & FILE_ATTRIBUTE_SYSTEM) &&
+ if ((dosattr & FILE_ATTRIBUTE_SYSTEM) &&
!(sattr & FILE_ATTRIBUTE_SYSTEM))
return (B_FALSE);
@@ -1850,14 +1837,14 @@
int rc;
ASSERT(id);
- ASSERT(id->i_sidattr.sid);
+ ASSERT(id->i_sid);
ksid->ks_id = id->i_id;
- smb_sid_tostr(id->i_sidattr.sid, sidstr);
+ smb_sid_tostr(id->i_sid, sidstr);
rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
ASSERT(rc == 0);
- ksid->ks_attr = id->i_sidattr.attrs;
+ ksid->ks_attr = id->i_attrs;
ksid->ks_domain = ksid_lookupdomain(sidstr);
}
@@ -1868,19 +1855,18 @@
* access token.
*/
static ksidlist_t *
-smb_cred_set_sidlist(smb_win_grps_t *token_grps)
+smb_cred_set_sidlist(smb_ids_t *token_grps)
{
int i;
ksidlist_t *lp;
- lp = kmem_zalloc(KSIDLIST_MEM(token_grps->wg_count), KM_SLEEP);
+ lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
lp->ksl_ref = 1;
- lp->ksl_nsid = token_grps->wg_count;
+ lp->ksl_nsid = token_grps->i_cnt;
lp->ksl_neid = 0;
for (i = 0; i < lp->ksl_nsid; i++) {
- smb_cred_set_sid(&token_grps->wg_groups[i],
- &lp->ksl_sids[i]);
+ smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
lp->ksl_neid++;
}
@@ -1910,8 +1896,8 @@
ASSERT(cr != NULL);
posix_grps = token->tkn_posix_grps;
- if (crsetugid(cr, token->tkn_user->i_id,
- token->tkn_primary_grp->i_id) != 0) {
+ if (crsetugid(cr, token->tkn_user.i_id,
+ token->tkn_primary_grp.i_id) != 0) {
crfree(cr);
return (NULL);
}
@@ -1921,13 +1907,13 @@
return (NULL);
}
- smb_cred_set_sid(token->tkn_user, &ksid);
+ smb_cred_set_sid(&token->tkn_user, &ksid);
crsetsid(cr, &ksid, KSID_USER);
- smb_cred_set_sid(token->tkn_primary_grp, &ksid);
+ smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
crsetsid(cr, &ksid, KSID_GROUP);
- smb_cred_set_sid(token->tkn_owner, &ksid);
+ smb_cred_set_sid(&token->tkn_owner, &ksid);
crsetsid(cr, &ksid, KSID_OWNER);
- ksidlist = smb_cred_set_sidlist(token->tkn_win_grps);
+ ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
crsetsidlist(cr, ksidlist);
*privileges = 0;
@@ -1982,7 +1968,7 @@
ASSERT(cr);
bzero(&id, sizeof (smb_id_t));
- id.i_sidattr.sid = sid;
+ id.i_sid = sid;
smb_cred_set_sid(&id, &ksid1);
ksidlist = crgetsidlist(cr);
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c Sun Feb 01 19:44:54 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.
*/
@@ -40,36 +40,13 @@
#include <smbsrv/smb_vops.h>
#include <smbsrv/string.h>
-#include <smbsrv/smbtrans.h>
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_incl.h>
-void
-smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr);
-
-static int
-smb_vop_readdir_readpage(vnode_t *, void *, uint32_t, int *, cred_t *);
-
-static int
-smb_vop_readdir_entry(vnode_t *, uint32_t *, char *, int *,
- ino64_t *, vnode_t **, char *, int, cred_t *, char *, int);
-
-static int
-smb_vop_getdents_entries(smb_node_t *, uint32_t *, int32_t *, char *, uint32_t,
- smb_request_t *, cred_t *, char *, int *, int, char *);
-
-extern int
-smb_gather_dents_info(char *args, ino_t fileid, int namelen,
- char *name, uint32_t cookie, int32_t *countp,
- smb_attr_t *attr, struct smb_node *snode,
- char *shortname, char *name83);
-
-static void
-smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp);
-
-static
-callb_cpr_t *smb_lock_frlock_callback(flk_cb_when_t, void *);
+static void smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr);
+static void smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp);
+static callb_cpr_t *smb_lock_frlock_callback(flk_cb_when_t, void *);
extern sysid_t lm_alloc_sysidt();
@@ -235,6 +212,8 @@
*
* File systems without VFSFT_XVATTR do not support DOS attributes or create
* time (crtime). In this case the mtime is used as the crtime.
+ * Likewise if VOP_GETATTR doesn't return any system attributes the dosattr
+ * is 0 and the mtime is used as the crtime.
*/
int
smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
@@ -273,68 +252,49 @@
ret_attr->sa_vattr = tmp_xvattr.xva_vattr;
ret_attr->sa_dosattr = 0;
- ASSERT(tmp_xvattr.xva_vattr.va_mask & AT_XVATTR);
-
- xoap = xva_getxoptattr(&tmp_xvattr);
- ASSERT(xoap);
+ if (tmp_xvattr.xva_vattr.va_mask & AT_XVATTR) {
+ xoap = xva_getxoptattr(&tmp_xvattr);
+ ASSERT(xoap);
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_READONLY)) {
- if (xoap->xoa_readonly)
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_READONLY)) &&
+ (xoap->xoa_readonly)) {
ret_attr->sa_dosattr |= FILE_ATTRIBUTE_READONLY;
- }
-
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_HIDDEN)) {
- if (xoap->xoa_hidden)
- ret_attr->sa_dosattr |= FILE_ATTRIBUTE_HIDDEN;
- }
+ }
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_SYSTEM)) {
- if (xoap->xoa_system)
- ret_attr->sa_dosattr |= FILE_ATTRIBUTE_SYSTEM;
- }
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_HIDDEN)) &&
+ (xoap->xoa_hidden)) {
+ ret_attr->sa_dosattr |= FILE_ATTRIBUTE_HIDDEN;
+ }
- if (XVA_ISSET_RTN(&tmp_xvattr, XAT_ARCHIVE)) {
- if (xoap->xoa_archive)
- ret_attr->sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE;
- }
-
- ret_attr->sa_crtime = xoap->xoa_createtime;
-
- if (unnamed_vp) {
- ret_attr->sa_vattr.va_type = VREG;
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_SYSTEM)) &&
+ (xoap->xoa_system)) {
+ ret_attr->sa_dosattr |= FILE_ATTRIBUTE_SYSTEM;
+ }
- if (ret_attr->sa_mask & SMB_AT_SIZE) {
- tmp_xvattr.xva_vattr.va_mask = AT_SIZE;
-
- error = VOP_GETATTR(vp, &tmp_xvattr.xva_vattr,
- flags, cr, &smb_ct);
- if (error != 0)
- return (error);
-
- ret_attr->sa_vattr.va_size =
- tmp_xvattr.xva_vattr.va_size;
-
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_ARCHIVE)) &&
+ (xoap->xoa_archive)) {
+ ret_attr->sa_dosattr |= FILE_ATTRIBUTE_ARCHIVE;
}
- }
- if (ret_attr->sa_vattr.va_type == VDIR)
- ret_attr->sa_dosattr |= FILE_ATTRIBUTE_DIRECTORY;
-
- return (error);
- }
+ ret_attr->sa_crtime = xoap->xoa_createtime;
+ } else {
+ ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
+ }
+ } else {
+ /*
+ * Support for file systems without VFSFT_XVATTR
+ */
+ smb_sa_to_va_mask(ret_attr->sa_mask,
+ &ret_attr->sa_vattr.va_mask);
- /*
- * Support for file systems without VFSFT_XVATTR
- */
- smb_sa_to_va_mask(ret_attr->sa_mask,
- &ret_attr->sa_vattr.va_mask);
+ error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr,
+ flags, cr, &smb_ct);
+ if (error != 0)
+ return (error);
- error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, &smb_ct);
- if (error != 0)
- return (error);
-
- ret_attr->sa_dosattr = 0;
- ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
+ ret_attr->sa_dosattr = 0;
+ ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
+ }
if (unnamed_vp) {
ret_attr->sa_vattr.va_type = VREG;
@@ -676,7 +636,7 @@
return (VOP_FSYNC(vp, 1, cr, &smb_ct));
}
-void
+static void
smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr)
{
xoptattr_t *xoap = NULL;
@@ -753,116 +713,27 @@
}
}
-
/*
* smb_vop_readdir()
*
- * Upon return, the "name" field will contain either the on-disk name or, if
- * it needs mangling or has a case-insensitive collision, the mangled
- * "shortname."
+ * Collects an SMB_MINLEN_RDDIR_BUF "page" of directory entries.
+ * The directory entries are returned in an fs-independent format by the
+ * underlying file system. That is, the "page" of information returned is
+ * not literally stored on-disk in the format returned.
+ * If the file system supports extended directory entries (has features
+ * VFSFT_DIRENTFLAGS), set V_RDDIR_ENTFLAGS to cause the buffer to be
+ * filled with edirent_t structures, instead of dirent64_t structures.
*
- * vpp is an optional parameter. If non-NULL, it will contain a pointer to
- * the vnode for the name that is looked up (the vnode will be returned held).
- *
- * od_name is an optional parameter (NULL can be passed if the on-disk name
- * is not needed by the caller).
+ * Some file systems can have directories larger than SMB_MAXDIRSIZE.
+ * After VOP_READDIR, if offset is larger than SMB_MAXDIRSIZE treat as EOF.
*/
-
int
-smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen,
- ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr)
-{
- int num_bytes;
- int error = 0;
- char *dirbuf = NULL;
-
- ASSERT(dvp);
- ASSERT(cookiep);
- ASSERT(name);
- ASSERT(namelen);
- ASSERT(inop);
- ASSERT(cr);
-
- if (dvp->v_type != VDIR) {
- *namelen = 0;
- return (ENOTDIR);
- }
-
- if (vpp)
- *vpp = NULL;
-
- dirbuf = kmem_zalloc(SMB_MINLEN_RDDIR_BUF, KM_SLEEP);
- num_bytes = SMB_MINLEN_RDDIR_BUF;
-
- /*
- * The goal is to retrieve the first valid entry from *cookiep
- * forward. smb_vop_readdir_readpage() collects an
- * SMB_MINLEN_RDDIR_BUF-size "page" of directory entry information.
- * smb_vop_readdir_entry() attempts to find the first valid entry
- * in that page.
- */
-
- while ((error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep,
- &num_bytes, cr)) == 0) {
-
- if (num_bytes <= 0)
- break;
-
- name[0] = '\0';
-
- error = smb_vop_readdir_entry(dvp, cookiep, name, namelen,
- inop, vpp, od_name, flags, cr, dirbuf, num_bytes);
-
- if (error)
- break;
-
- if (*name)
- break;
-
- bzero(dirbuf, SMB_MINLEN_RDDIR_BUF);
- num_bytes = SMB_MINLEN_RDDIR_BUF;
- }
-
-
- if (error) {
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- *namelen = 0;
- return (error);
- }
-
- if (num_bytes == 0) { /* EOF */
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- *cookiep = SMB_EOF;
- *namelen = 0;
- return (0);
- }
-
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
- return (0);
-}
-
-/*
- * smb_vop_readdir_readpage()
- *
- * Collects an SMB_MINLEN_RDDIR_BUF "page" of directory entries. (The
- * directory entries are returned in an fs-independent format by the
- * underlying file system. That is, the "page" of information returned is
- * not literally stored on-disk in the format returned.)
- *
- * Much of the following is borrowed from getdents64()
- *
- * MAXGETDENTS_SIZE is defined in getdents.c
- */
-
-#define MAXGETDENTS_SIZE (64 * 1024)
-
-static int
-smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count,
- cred_t *cr)
+smb_vop_readdir(vnode_t *vp, uint32_t offset,
+ void *buf, int *count, int *eof, cred_t *cr)
{
int error = 0;
int rdirent_flags = 0;
- int sink;
+ int rdirent_size;
struct uio auio;
struct iovec aiov;
@@ -870,22 +741,14 @@
return (ENOTDIR);
if (vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*
- * Setting V_RDDIR_ENTFLAGS will cause the buffer to
- * be filled with edirent_t structures (instead of
- * dirent64_t structures).
- */
rdirent_flags = V_RDDIR_ENTFLAGS;
-
- if (*count < sizeof (edirent_t))
- return (EINVAL);
+ rdirent_size = sizeof (edirent_t);
} else {
- if (*count < sizeof (dirent64_t))
- return (EINVAL);
+ rdirent_size = sizeof (dirent64_t);
}
- if (*count > MAXGETDENTS_SIZE)
- *count = MAXGETDENTS_SIZE;
+ if (*count < rdirent_size)
+ return (EINVAL);
aiov.iov_base = buf;
aiov.iov_len = *count;
@@ -897,183 +760,14 @@
auio.uio_fmode = 0;
(void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
- error = VOP_READDIR(vp, &auio, cr, &sink, &smb_ct, rdirent_flags);
+ error = VOP_READDIR(vp, &auio, cr, eof, &smb_ct, rdirent_flags);
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
- if (error) {
- if (error == ENOENT) {
- /* Fake EOF if offset is bad due to dropping of lock */
- *count = 0;
- return (0);
- } else {
- return (error);
- }
- }
-
- /*
- * Windows cannot handle an offset > SMB_EOF.
- * Pretend we are at EOF.
- */
-
- if (auio.uio_loffset > SMB_EOF) {
- *count = 0;
- return (0);
- }
-
- *count = *count - auio.uio_resid;
- return (0);
-}
-
-/*
- * smb_vop_readdir_entry()
- *
- * This function retrieves the first valid entry from the
- * SMB_MINLEN_RDDIR_BUF-sized buffer returned by smb_vop_readdir_readpage()
- * to smb_vop_readdir().
- *
- * Both dirent64_t and edirent_t structures need to be handled. The former is
- * needed for file systems that do not support VFSFT_DIRENTFLAGS. The latter
- * is required for proper handling of case collisions on file systems that
- * support case-insensitivity. edirent_t structures are also used for
- * case-sensitive file systems if VFSFT_DIRENTFLAGS is supported.
- */
-
-static int
-smb_vop_readdir_entry(
- vnode_t *dvp,
- uint32_t *cookiep,
- char *name,
- int *namelen,
- ino64_t *inop,
- vnode_t **vpp,
- char *od_name,
- int flags,
- cred_t *cr,
- char *dirbuf,
- int num_bytes)
-{
- uint32_t next_cookie;
- int ebufsize;
- int error = 0;
- int len;
- int rc;
- char shortname[SMB_SHORTNAMELEN];
- char name83[SMB_SHORTNAMELEN];
- char *ebuf = NULL;
- edirent_t *edp;
- dirent64_t *dp = NULL;
- vnode_t *vp = NULL;
-
- ASSERT(dirbuf);
-
- /*
- * Use edirent_t structure for both
- */
- if (vfs_has_feature(dvp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)dirbuf;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- dp = (dirent64_t *)dirbuf;
- ebufsize = EDIRENT_RECLEN(MAXNAMELEN);
- ebuf = kmem_zalloc(ebufsize, KM_SLEEP);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)ebuf;
- }
-
- while (edp) {
- if (dp)
- DP_TO_EDP(dp, edp);
+ if (auio.uio_loffset > SMB_MAXDIRSIZE)
+ *eof = 1;
- next_cookie = (uint32_t)edp->ed_off;
- if (edp->ed_ino == 0) {
- *cookiep = next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
- len = strlen(edp->ed_name);
-
- if (*namelen < len) {
- *namelen = 0;
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (EOVERFLOW);
- }
-
- /*
- * Do not pass SMB_IGNORE_CASE to smb_vop_lookup
- */
-
- error = smb_vop_lookup(dvp, edp->ed_name, vpp ? vpp : &vp,
- od_name, 0, NULL, cr);
-
- if (error) {
- if (error == ENOENT) {
- *cookiep = (uint32_t)next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
-
- *namelen = 0;
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (error);
- }
-
- if ((flags & SMB_IGNORE_CASE) && ED_CASE_CONFLICTS(edp)) {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 1);
-
- if (rc == 1) { /* success */
- (void) strlcpy(name, shortname, *namelen + 1);
- *namelen = strlen(shortname);
- } else {
- (void) strlcpy(name, edp->ed_name,
- *namelen + 1);
- name[*namelen] = '\0';
- }
-
- } else {
- (void) strlcpy(name, edp->ed_name, *namelen + 1);
- *namelen = len;
- }
-
- if (vpp == NULL)
- VN_RELE(vp);
-
- if (inop)
- *inop = edp->ed_ino;
-
- *cookiep = (uint32_t)next_cookie;
- break;
- }
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
+ if (error == 0)
+ *count = *count - auio.uio_resid;
return (error);
}
@@ -1102,266 +796,6 @@
}
/*
- * smb_vop_getdents()
- *
- * Upon success, the smb_node corresponding to each entry returned will
- * have a reference taken on it. These will be released in
- * smb_trans2_find_get_dents().
- *
- * If an error is returned from this routine, a list of already processed
- * entries will be returned. The smb_nodes corresponding to these entries
- * will be referenced, and will be released in smb_trans2_find_get_dents().
- *
- * The returned dp->d_name field will contain either the on-disk name or, if
- * it needs mangling or has a case-insensitive collision, the mangled
- * "shortname." In this case, the on-disk name can be retrieved from the
- * smb_node's od_name (the smb_node is passed to smb_gather_dents_info()).
- */
-
-int /*ARGSUSED*/
-smb_vop_getdents(
- smb_node_t *dir_snode,
- uint32_t *cookiep,
- uint64_t *verifierp,
- int32_t *dircountp,
- char *arg,
- char *pattern,
- uint32_t flags,
- smb_request_t *sr,
- cred_t *cr)
-{
- int error = 0;
- int maxentries;
- int num_bytes;
- int resid;
- char *dirbuf = NULL;
- vnode_t *dvp;
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)arg;
-
- dvp = dir_snode->vp;
-
- resid = ihdr->uio.uio_resid;
- maxentries = resid / SMB_MAX_DENT_INFO_SIZE;
-
- bzero(ihdr->iov->iov_base, resid);
-
- dirbuf = kmem_alloc(SMB_MINLEN_RDDIR_BUF, KM_SLEEP);
-
- while (maxentries) {
-
- bzero(dirbuf, SMB_MINLEN_RDDIR_BUF);
-
- num_bytes = SMB_MINLEN_RDDIR_BUF;
- error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep,
- &num_bytes, cr);
-
- if (error || (num_bytes <= 0))
- break;
-
- error = smb_vop_getdents_entries(dir_snode, cookiep, dircountp,
- arg, flags, sr, cr, dirbuf, &maxentries, num_bytes,
- pattern);
-
- if (error)
- goto out;
- }
-
- if (num_bytes < 0) {
- error = -1;
- } else if (num_bytes == 0) {
- *cookiep = SMB_EOF;
- error = 0;
- } else {
- error = 0;
- }
-
-out:
- if (dirbuf)
- kmem_free(dirbuf, SMB_MINLEN_RDDIR_BUF);
-
- return (error);
-}
-
-/*
- * smb_vop_getdents_entries()
- *
- * This function retrieves names from the SMB_MINLEN_RDDIR_BUF-sized buffer
- * returned by smb_vop_readdir_readpage() to smb_vop_getdents().
- *
- * Both dirent64_t and edirent_t structures need to be handled. The former is
- * needed for file systems that do not support VFSFT_DIRENTFLAGS. The latter
- * is required for properly handling case collisions on file systems that
- * support case-insensitivity. edirent_t is also used on case-sensitive
- * file systems where VFSFT_DIRENTFLAGS is available.
- */
-
-static int
-smb_vop_getdents_entries(
- smb_node_t *dir_snode,
- uint32_t *cookiep,
- int32_t *dircountp,
- char *arg,
- uint32_t flags,
- smb_request_t *sr,
- cred_t *cr,
- char *dirbuf,
- int *maxentries,
- int num_bytes,
- char *pattern)
-{
- uint32_t next_cookie;
- int ebufsize;
- char *tmp_name;
- int rc;
- char shortname[SMB_SHORTNAMELEN];
- char name83[SMB_SHORTNAMELEN];
- char *ebuf = NULL;
- dirent64_t *dp = NULL;
- edirent_t *edp;
- smb_node_t *ret_snode;
- smb_attr_t ret_attr;
- vnode_t *dvp;
- vnode_t *fvp;
-
- ASSERT(dirbuf);
-
- dvp = dir_snode->vp;
-
- if (vfs_has_feature(dvp->v_vfsp, VFSFT_DIRENTFLAGS)) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)dirbuf;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- dp = (dirent64_t *)dirbuf;
- ebufsize = EDIRENT_RECLEN(MAXNAMELEN);
- ebuf = kmem_zalloc(ebufsize, KM_SLEEP);
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- edp = (edirent_t *)ebuf;
- }
-
- while (edp) {
- if (dp)
- DP_TO_EDP(dp, edp);
-
- if (*maxentries == 0)
- break;
-
- next_cookie = (uint32_t)edp->ed_off;
-
- if (edp->ed_ino == 0) {
- *cookiep = next_cookie;
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- continue;
- }
-
- rc = smb_vop_lookup(dvp, edp->ed_name, &fvp,
- NULL, 0, NULL, cr);
-
- if (rc) {
- if (rc == ENOENT) {
- *cookiep = next_cookie;
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf,
- num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf,
- num_bytes);
- }
- continue;
- }
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (rc);
- }
-
- ret_snode = smb_node_lookup(sr, NULL, cr, fvp,
- edp->ed_name, dir_snode, NULL, &ret_attr);
-
- if (ret_snode == NULL) {
- VN_RELE(fvp);
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (ENOMEM);
- }
-
- if (smb_match_name(edp->ed_ino, edp->ed_name, shortname,
- name83, pattern, (flags & SMB_IGNORE_CASE))) {
-
- tmp_name = edp->ed_name;
-
- if ((flags & SMB_IGNORE_CASE) &&
- ED_CASE_CONFLICTS(edp)) {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 1);
- if (rc == 1)
- tmp_name = shortname;
- } else {
- rc = smb_mangle_name(edp->ed_ino, edp->ed_name,
- shortname, name83, 0);
- }
-
- if (rc != 1) {
- (void) strlcpy(shortname, edp->ed_name,
- SMB_SHORTNAMELEN);
- (void) strlcpy(name83, edp->ed_name,
- SMB_SHORTNAMELEN);
- shortname[SMB_SHORTNAMELEN - 1] = '\0';
- name83[SMB_SHORTNAMELEN - 1] = '\0';
- }
-
- rc = smb_gather_dents_info(arg, edp->ed_ino,
- strlen(tmp_name), tmp_name, next_cookie, dircountp,
- &ret_attr, ret_snode, shortname, name83);
-
- if (rc < 0) {
- if (ebuf)
- kmem_free(ebuf, ebufsize);
- *maxentries = 0;
- return (0);
- }
-
- if (rc > 0)
- (*maxentries)--;
- } else {
- smb_node_release(ret_snode);
- }
-
- *cookiep = next_cookie;
-
- if (dp) {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- DP_ADVANCE(dp, dirbuf, num_bytes);
- if (dp == NULL)
- edp = NULL;
- } else {
- /*LINTED E_BAD_PTR_CAST_ALIGN*/
- EDP_ADVANCE(edp, dirbuf, num_bytes);
- }
- }
-
- if (ebuf)
- kmem_free(ebuf, ebufsize);
-
- return (0);
-}
-
-/*
* smb_vop_stream_lookup()
*
* The name returned in od_name is the on-disk name of the stream with the
@@ -1472,80 +906,6 @@
return (error);
}
-/*
- * smb_vop_stream_readdir()
- *
- * Note: stream_info.size is not filled in in this routine.
- * It needs to be filled in by the caller due to the parameters for getattr.
- *
- * stream_info.name is set to the on-disk stream name with the SMB_STREAM_PREFIX
- * removed.
- */
-
-int
-smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep,
- struct fs_stream_info *stream_info, vnode_t **vpp, vnode_t **xattrdirvpp,
- int flags, cred_t *cr)
-{
- int nsize;
- int error = 0;
- ino64_t ino;
- char *tmp_name;
- vnode_t *xattrdirvp;
- vnode_t *vp;
-
- if ((error = smb_vop_lookup_xattrdir(fvp, &xattrdirvp, LOOKUP_XATTR,
- cr)) != 0)
- return (error);
-
- bzero(stream_info->name, sizeof (stream_info->name));
- stream_info->size = 0;
-
- tmp_name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
-
- for (;;) {
- nsize = MAXNAMELEN-1;
- error = smb_vop_readdir(xattrdirvp, cookiep, tmp_name, &nsize,
- &ino, &vp, NULL, flags, cr);
-
- if (error || (*cookiep == SMB_EOF))
- break;
-
- if (strncmp(tmp_name, SMB_STREAM_PREFIX,
- SMB_STREAM_PREFIX_LEN)) {
- VN_RELE(vp);
- continue;
- }
-
- tmp_name[nsize] = '\0';
- (void) strlcpy(stream_info->name,
- &(tmp_name[SMB_STREAM_PREFIX_LEN]),
- sizeof (stream_info->name));
-
- nsize -= SMB_STREAM_PREFIX_LEN;
- break;
- }
-
- if ((error == 0) && nsize) {
- if (vpp)
- *vpp = vp;
- else
- VN_RELE(vp);
-
- if (xattrdirvpp)
- *xattrdirvpp = xattrdirvp;
- else
- VN_RELE(xattrdirvp);
-
- } else {
- VN_RELE(xattrdirvp);
- }
-
- kmem_free(tmp_name, MAXNAMELEN);
-
- return (error);
-}
-
int
smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, int flags,
cred_t *cr)
--- a/usr/src/uts/common/fs/smbsrv/smb_vss.c Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/fs/smbsrv/smb_vss.c Sun Feb 01 19:44:54 2009 -0700
@@ -201,12 +201,19 @@
/* note the value of cur_node->vp */
err = vnodetopath(fsrootvp, cur_node->vp, nodepath,
MAXPATHLEN, kcred);
-
- if (err != 0)
+ if (err != 0) {
+ VN_RELE(vp);
goto error;
+ }
*vss_root_node = smb_node_lookup(sr, NULL, kcred, vp,
gmttoken, cur_node, NULL, &attr);
+ VN_RELE(vp);
+
+ if (*vss_root_node == NULL) {
+ err = ENOENT;
+ goto error;
+ }
(void) snprintf(rootpath, MAXPATHLEN, ".zfs/snapshot/%s/%s",
snapname, nodepath);
@@ -217,6 +224,8 @@
if (vp) {
*vss_cur_node = smb_node_lookup(sr, NULL, kcred, vp,
gmttoken, cur_node, NULL, &attr);
+ VN_RELE(vp);
+
if (*vss_cur_node != NULL) {
smb_vss_remove_first_token_from_path(buf);
} else {
--- a/usr/src/uts/common/smbsrv/Makefile Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/Makefile Sun Feb 01 19:44:54 2009 -0700
@@ -19,10 +19,8 @@
# 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.
-#
-# ident "@(#)Makefile 1.6 08/08/07 SMI"
include ../../../Makefile.master
@@ -66,6 +64,7 @@
smb_i18n.h \
smb_idmap.h \
smb_incl.h \
+ smb_inet.h \
smb_ioctl.h \
smb_kproto.h \
smb_kstat.h \
@@ -77,7 +76,6 @@
smb_xdr.h \
smbfmt.h \
smbinfo.h \
- smbtrans.h \
string.h \
svrapi.h \
winioctl.h \
--- a/usr/src/uts/common/smbsrv/cifs.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/cifs.h Sun Feb 01 19:44:54 2009 -0700
@@ -538,7 +538,7 @@
/*
* Flags for TRANS2_FIND_FIRST2 and TRANS2_FIND_NEXT2
- * (NTDDK cifs.h and smbtrans.h).
+ * (NTDDK cifs.h).
*
* If SMB_FIND_RETURN_RESUME_KEYS was set in the request parameters,
* each entry is preceded by a four-byte resume key.
--- a/usr/src/uts/common/smbsrv/netrauth.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/netrauth.h Sun Feb 01 19:44:54 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.
*/
@@ -35,6 +35,8 @@
#include <sys/types.h>
#include <smbsrv/wintypes.h>
#include <smbsrv/netbios.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smbinfo.h>
#ifndef _KERNEL
#include <syslog.h>
@@ -111,24 +113,14 @@
time_t timestamp;
} netr_info_t;
-/*
- * netr_client_t flags
- *
- * NETR_CFLG_ANON Anonymous connection
- * NETR_CFLG_LOCAL Local user
- * NETR_CFLG_DOMAIN Domain user
- */
-#define NETR_CFLG_ANON 0x01
-#define NETR_CFLG_LOCAL 0x02
-#define NETR_CFLG_DOMAIN 0x04
-
-
typedef struct netr_client {
uint16_t logon_level;
char *username;
char *domain;
+ char *real_username;
+ char *real_domain;
char *workstation;
- uint32_t ipaddr;
+ smb_inaddr_t ipaddr;
struct {
uint32_t challenge_key_len;
uint8_t *challenge_key_val;
@@ -144,9 +136,8 @@
uint32_t logon_id;
int native_os;
int native_lm;
- uint32_t local_ipaddr;
+ smb_inaddr_t local_ipaddr;
uint16_t local_port;
- uint32_t flags;
} netr_client_t;
--- a/usr/src/uts/common/smbsrv/smb_door_svc.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_door_svc.h Sun Feb 01 19:44:54 2009 -0700
@@ -150,14 +150,14 @@
/*
* SMB upcalls
*/
-smb_token_t *smb_upcall_get_token(netr_client_t *);
+smb_token_t *smb_get_token(netr_client_t *);
int smb_set_downcall_desc(door_desc_t *, uint_t);
void smb_user_nonauth_logon(uint32_t);
void smb_user_auth_logoff(uint32_t);
uint32_t smb_upcall_vss_get_count(char *);
-void smb_upcall_vss_get_snapshots(char *resource_path, uint32_t count,
- smb_dr_return_gmttokens_t *gmttokens);
-void smb_upcall_vss_get_snapshots_free(smb_dr_return_gmttokens_t *reply);
+void smb_upcall_vss_get_snapshots(char *, uint32_t,
+ smb_dr_return_gmttokens_t *);
+void smb_upcall_vss_get_snapshots_free(smb_dr_return_gmttokens_t *);
void smb_upcall_vss_map_gmttoken(char *, char *, char *);
#else /* _KERNEL */
--- a/usr/src/uts/common/smbsrv/smb_fsops.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_fsops.h Sun Feb 01 19:44:54 2009 -0700
@@ -19,15 +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_FSOPS_H
#define _SMBSRV_SMB_FSOPS_H
-#pragma ident "@(#)smb_fsops.h 1.8 08/07/15 SMI"
-
/*
* This header file contains all the functions for the interface between
* the smb layer and the fs layer.
@@ -68,15 +66,6 @@
int smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode,
smb_attr_t *attr);
-int smb_fsop_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *snode,
- uint32_t *cookie, char *name, int *namelen, ino64_t *fileid,
- struct fs_stream_info *stream_info, smb_node_t **ret_snode,
- smb_attr_t *ret_attr);
-
-int smb_fsop_getdents(struct smb_request *sr, cred_t *cr,
- struct smb_node *dir_snode, uint32_t *cookie, uint64_t *verifierp,
- int32_t *maxcnt, char *args, char *pattern);
-
int smb_maybe_mangled_name(char *name);
int smb_fsop_rename(struct smb_request *sr, cred_t *cr,
@@ -115,10 +104,6 @@
int smb_fsop_commit(smb_request_t *sr, cred_t *cr, struct smb_node *snode);
-int smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr,
- smb_node_t *fnode, uint32_t *cookiep, struct fs_stream_info *stream_info,
- smb_node_t **ret_snode, smb_attr_t *ret_attr);
-
int smb_fsop_aclread(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *);
int smb_fsop_aclwrite(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *);
acl_type_t smb_fsop_acltype(smb_node_t *);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/smbsrv/smb_inet.h Sun Feb 01 19:44:54 2009 -0700
@@ -0,0 +1,71 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file was originally generated using rpcgen.
+ */
+
+#ifndef _SMB_INET_H
+#define _SMB_INET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _KERNEL
+#include <inet/tcp.h>
+#include <arpa/inet.h>
+#endif /* !_KERNEL */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+typedef struct smb_inaddr {
+ union {
+ in_addr_t au_ipv4;
+ in6_addr_t au_ipv6;
+ in6_addr_t au_ip;
+ } au_addr;
+ int a_family;
+} smb_inaddr_t;
+
+#define a_ipv4 au_addr.au_ipv4
+#define a_ipv6 au_addr.au_ipv6
+#define a_ip au_addr.au_ip
+
+#define SMB_IPSTRLEN(family) \
+((family == AF_INET) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN)
+
+#define SMB_INET_NOMASK 0xffffffff
+
+boolean_t smb_inet_equal(smb_inaddr_t *, smb_inaddr_t *, uint32_t);
+boolean_t smb_inet_iszero(smb_inaddr_t *);
+const char *smb_inet_ntop(smb_inaddr_t *, char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMB_INET_H */
--- a/usr/src/uts/common/smbsrv/smb_kproto.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h Sun Feb 01 19:44:54 2009 -0700
@@ -208,7 +208,7 @@
#define SMB_SAME_SESSION(sess1, sess2) \
((sess1) && (sess2) && \
- ((sess1)->ipaddr == (sess2)->ipaddr) && \
+ (smb_inet_equal(&sess1->ipaddr, &sess2->ipaddr, 0)) && \
((sess1)->s_kid == (sess2)->s_kid)) \
#define SMB_ATTR_ONLY_OPEN(op) \
@@ -248,10 +248,6 @@
int smb_ascii_or_unicode_null_len(struct smb_request *);
int smb_search(struct smb_request *);
-void smb_rdir_close(struct smb_request *);
-int smb_rdir_open(struct smb_request *, char *, unsigned short);
-int smb_rdir_next(smb_request_t *sr, smb_node_t **rnode,
- smb_odir_context_t *pc);
uint32_t smb_common_open(smb_request_t *);
DWORD smb_validate_object_name(char *path, unsigned int ftype);
@@ -295,10 +291,7 @@
char *smb_xlate_com_cd_to_str(int);
char *smb_xlate_dialect_cd_to_str(int);
-void smb_od_destruct(struct smb_session *, struct smb_odir *);
int smbd_fs_query(smb_request_t *, smb_fqi_t *, int);
-int smb_component_match(struct smb_request *sr, ino64_t fileid,
- struct smb_odir *od, smb_odir_context_t *pc);
int smb_lock_range_access(struct smb_request *, struct smb_node *,
uint64_t, uint64_t, boolean_t);
@@ -481,14 +474,14 @@
void smb_sign_reply(struct smb_request *req, struct mbuf_chain *reply);
-boolean_t smb_sattr_check(smb_attr_t *, char *, unsigned short);
+boolean_t smb_sattr_check(uint16_t, uint16_t, char *);
void smb_request_cancel(smb_request_t *sr);
/*
* session functions (file smb_session.c)
*/
-smb_session_t *smb_session_create(ksocket_t, uint16_t, smb_server_t *);
+smb_session_t *smb_session_create(ksocket_t, uint16_t, smb_server_t *, int);
int smb_session_daemon(smb_session_list_t *);
void smb_session_reconnection_check(smb_session_list_t *, smb_session_t *);
void smb_session_timers(smb_session_list_t *);
@@ -539,13 +532,21 @@
/*
* odir functions (file smb_odir.c)
*/
-smb_odir_t *smb_odir_open(smb_tree_t *tree, smb_node_t *node, char *pattern,
- uint16_t pid, unsigned short sattr);
-void smb_odir_close(smb_odir_t *od);
-void smb_odir_close_all(smb_tree_t *tree);
-void smb_odir_close_all_by_pid(smb_tree_t *tree, uint16_t pid);
-void smb_odir_release(smb_odir_t *od);
-smb_odir_t *smb_odir_lookup_by_sid(smb_tree_t *tree, uint16_t sid);
+uint16_t smb_odir_open(smb_request_t *, char *, uint16_t);
+uint16_t smb_odir_openat(smb_request_t *, smb_node_t *);
+void smb_odir_close(smb_odir_t *);
+boolean_t smb_odir_hold(smb_odir_t *);
+void smb_odir_release(smb_odir_t *);
+
+int smb_odir_read(smb_request_t *, smb_odir_t *,
+ smb_odirent_t *, boolean_t *);
+int smb_odir_read_fileinfo(smb_request_t *, smb_odir_t *,
+ smb_fileinfo_t *, boolean_t *);
+int smb_odir_read_streaminfo(smb_request_t *, smb_odir_t *,
+ smb_streaminfo_t *, boolean_t *);
+
+void smb_odir_save_cookie(smb_odir_t *, int, uint32_t cookie);
+void smb_odir_resume_at(smb_odir_t *, smb_odir_resume_t *);
/*
* SMB user functions (file smb_user.c)
@@ -579,8 +580,8 @@
boolean_t smb_tree_has_feature(smb_tree_t *, uint_t);
boolean_t smb_tree_hold(smb_tree_t *);
void smb_tree_release(smb_tree_t *);
-
void smb_dr_ulist_free(smb_dr_ulist_t *ulist);
+smb_odir_t *smb_tree_lookup_odir(smb_tree_t *, uint16_t);
/*
* SMB user's credential functions
@@ -625,7 +626,7 @@
int uioxfer(struct uio *src_uio, struct uio *dst_uio, int n);
-int smb_match_name(ino64_t, char *, char *, char *, char *, boolean_t);
+int smb_match_name(ino64_t, char *, char *, boolean_t);
boolean_t smb_is_dot_or_dotdot(const char *);
int token2buf(smb_token_t *token, char *buf);
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h Sun Feb 01 19:44:54 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.
*/
@@ -50,6 +50,7 @@
#include <sys/ksocket.h>
#include <sys/fem.h>
#include <sys/door.h>
+#include <sys/extdirent.h>
#include <smbsrv/smb.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/mbuf.h>
@@ -75,9 +76,15 @@
*/
#define SMB_MAX_SEARCH 10
+#define SMB_SEARCH_ATTRIBUTES \
+ (FILE_ATTRIBUTE_HIDDEN | \
+ FILE_ATTRIBUTE_SYSTEM | \
+ FILE_ATTRIBUTE_DIRECTORY)
+
#define SMB_SEARCH_HIDDEN(sattr) ((sattr) & FILE_ATTRIBUTE_HIDDEN)
#define SMB_SEARCH_SYSTEM(sattr) ((sattr) & FILE_ATTRIBUTE_SYSTEM)
#define SMB_SEARCH_DIRECTORY(sattr) ((sattr) & FILE_ATTRIBUTE_DIRECTORY)
+#define SMB_SEARCH_ALL(sattr) ((sattr) & SMB_SEARCH_ATTRIBUTES)
extern uint32_t smb_audit_flags;
@@ -401,7 +408,7 @@
typedef struct smb_oplock {
struct smb_ofile *op_ofile;
uint32_t op_flags;
- uint32_t op_ipaddr;
+ smb_inaddr_t op_ipaddr;
uint64_t op_kid;
} smb_oplock_t;
@@ -677,8 +684,8 @@
uint64_t opentime;
uint16_t vcnumber;
uint16_t s_local_port;
- uint32_t ipaddr;
- uint32_t local_ipaddr;
+ smb_inaddr_t ipaddr;
+ smb_inaddr_t local_ipaddr;
char workstation[SMB_PI_MAX_HOST];
int dialect;
int native_os;
@@ -801,7 +808,7 @@
smb_idpool_t t_fid_pool;
smb_llist_t t_odir_list;
- smb_idpool_t t_sid_pool;
+ smb_idpool_t t_odid_pool;
uint32_t t_refcnt;
uint32_t t_flags;
@@ -955,12 +962,8 @@
pid_t f_pid;
} smb_ofile_t;
-/* odir flags bits */
-#define SMB_DIR_FLAG_OPEN 0x0001
-#define SMB_DIR_FLAG_CLOSE 0x0002
-#define SMB_DIR_CLOSED(dir) ((dir)->d_flags & SMB_DIR_FLAG_CLOSE)
-
-#define SMB_ODIR_MAGIC 0x4F444952 /* 'ODIR' */
+#define SMB_ODIR_MAGIC 0x4F444952 /* 'ODIR' */
+#define SMB_ODIR_BUFSIZE (8 * 1024)
typedef enum {
SMB_ODIR_STATE_OPEN = 0,
@@ -969,35 +972,78 @@
SMB_ODIR_STATE_SENTINEL
} smb_odir_state_t;
+typedef enum {
+ SMB_ODIR_RESUME_IDX,
+ SMB_ODIR_RESUME_COOKIE,
+ SMB_ODIR_RESUME_FNAME
+} smb_odir_resume_type_t;
+
+typedef struct smb_odir_resume {
+ smb_odir_resume_type_t or_type;
+ int or_idx;
+ uint32_t or_cookie;
+ char *or_fname;
+} smb_odir_resume_t;
+
typedef struct smb_odir {
uint32_t d_magic;
kmutex_t d_mutex;
list_node_t d_lnd;
smb_odir_state_t d_state;
-
smb_session_t *d_session;
smb_user_t *d_user;
smb_tree_t *d_tree;
-
- uint32_t d_refcnt;
- uint32_t d_cookie;
- uint32_t d_cookies[SMB_MAX_SEARCH];
- uint16_t d_sid;
+ smb_node_t *d_dnode;
+ uint16_t d_odid;
uint16_t d_opened_by_pid;
uint16_t d_sattr;
+ uint32_t d_refcnt;
+
+ boolean_t d_wildcards;
+ boolean_t d_ignore_case;
+ boolean_t d_xat;
+ boolean_t d_eof;
+ boolean_t d_is_edp;
+ int d_bufsize;
+ uint64_t d_offset;
+ union {
+ char *u_bufptr;
+ edirent_t *u_edp;
+ dirent64_t *u_dp;
+ } d_u;
+ uint32_t d_cookies[SMB_MAX_SEARCH];
char d_pattern[MAXNAMELEN];
- struct smb_node *d_dir_snode;
- unsigned int d_wildcards;
+ char d_buf[SMB_ODIR_BUFSIZE];
} smb_odir_t;
+#define d_bufptr d_u.u_bufptr
+#define d_edp d_u.u_edp
+#define d_dp d_u.u_dp
-typedef struct smb_odir_context {
- uint32_t dc_cookie;
- uint16_t dc_dattr;
- char dc_name[MAXNAMELEN]; /* Real 'Xxxx.yyy.xx' */
- char dc_name83[SMB_SHORTNAMELEN]; /* w/ dot 'XXXX .XX ' */
- char dc_shortname[SMB_SHORTNAMELEN]; /* w/ dot 'XXXX.XX' */
- smb_attr_t dc_attr;
-} smb_odir_context_t;
+typedef struct smb_odirent {
+ char od_name[MAXNAMELEN]; /* on disk name */
+ ino64_t od_ino;
+ uint32_t od_eflags;
+} smb_odirent_t;
+
+typedef struct smb_fileinfo {
+ char fi_name[MAXNAMELEN];
+ char fi_name83[SMB_SHORTNAMELEN];
+ char fi_shortname[SMB_SHORTNAMELEN];
+ uint32_t fi_cookie;
+ uint32_t fi_dosattr; /* DOS attributes */
+ uint64_t fi_nodeid; /* file system node id */
+ uint64_t fi_size; /* file size in bytes */
+ uint64_t fi_alloc_size; /* allocation size in bytes */
+ timestruc_t fi_atime; /* last access */
+ timestruc_t fi_mtime; /* last modification */
+ timestruc_t fi_ctime; /* last status change */
+ timestruc_t fi_crtime; /* file creation */
+} smb_fileinfo_t;
+
+typedef struct smb_streaminfo {
+ uint64_t si_size;
+ char si_name[MAXPATHLEN];
+} smb_streaminfo_t;
#define SMB_LOCK_MAGIC 0x4C4F434B /* 'LOCK' */
@@ -1295,14 +1341,12 @@
struct mbuf_chain smb_data;
uint16_t smb_fid; /* not in hdr, but common */
- uint16_t smb_sid; /* not in hdr, but common */
unsigned char andx_com;
uint16_t andx_off;
struct smb_tree *tid_tree;
struct smb_ofile *fid_ofile;
- struct smb_odir *sid_odir;
smb_user_t *uid_user;
union {
@@ -1457,6 +1501,7 @@
kt_did_t ld_ktdid;
ksocket_t ld_so;
struct sockaddr_in ld_sin;
+ struct sockaddr_in6 ld_sin6;
smb_session_list_t ld_session_list;
} smb_listener_daemon_t;
--- a/usr/src/uts/common/smbsrv/smb_privilege.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_privilege.h Sun Feb 01 19:44:54 2009 -0700
@@ -19,17 +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 _SMB_PRIVILEGE_H
#define _SMB_PRIVILEGE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <smbsrv/smb_xdr.h>
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -188,11 +184,6 @@
int smb_privset_query(smb_privset_t *privset, uint32_t id);
void smb_privset_log(smb_privset_t *privset);
-/* XDR routines */
-extern bool_t xdr_smb_luid_t();
-extern bool_t xdr_smb_luid_attrs_t();
-extern bool_t xdr_smb_privset_t();
-
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/smbsrv/smb_share.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_share.h Sun Feb 01 19:44:54 2009 -0700
@@ -211,7 +211,7 @@
uint32_t smb_shr_get(char *, smb_share_t *);
uint32_t smb_shr_modify(smb_share_t *);
uint32_t smb_shr_get_realpath(const char *, char *, int);
-void smb_shr_hostaccess(smb_share_t *, ipaddr_t);
+void smb_shr_hostaccess(smb_share_t *, smb_inaddr_t *);
boolean_t smb_shr_exists(char *);
int smb_shr_is_special(char *);
@@ -228,7 +228,6 @@
*/
uint32_t smb_share_list(int, smb_shrlist_t *);
int smb_share_count(void);
-uint32_t smb_share_get(char *, smb_share_t *);
uint32_t smb_share_delete(char *);
uint32_t smb_share_rename(char *, char *);
uint32_t smb_share_create(smb_share_t *);
@@ -238,7 +237,8 @@
door_handle_t smb_kshare_init(int);
void smb_kshare_fini(door_handle_t);
-uint32_t smb_kshare_getinfo(door_handle_t, char *, smb_share_t *, ipaddr_t);
+uint32_t smb_kshare_getinfo(door_handle_t, char *, smb_share_t *,
+ smb_inaddr_t *);
int smb_kshare_upcall(door_handle_t, void *, boolean_t);
uint32_t smb_kshare_enum(door_handle_t, smb_enumshare_info_t *);
--- a/usr/src/uts/common/smbsrv/smb_sid.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_sid.h Sun Feb 01 19:44:54 2009 -0700
@@ -216,6 +216,31 @@
} smb_sid_t;
/*
+ * Only group attributes are defined. No user attributes defined.
+ */
+#define SE_GROUP_MANDATORY 0x00000001
+#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002
+#define SE_GROUP_ENABLED 0x00000004
+#define SE_GROUP_OWNER 0x00000008
+#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010
+#define SE_GROUP_LOGON_ID 0xC0000000
+
+/*
+ * smb_id_t consists of both the Windows security identifier
+ * and its corresponding POSIX/ephemeral ID.
+ */
+typedef struct smb_id {
+ uint32_t i_attrs;
+ smb_sid_t *i_sid;
+ uid_t i_id;
+} smb_id_t;
+
+typedef struct smb_ids {
+ uint32_t i_cnt;
+ smb_id_t *i_ids;
+} smb_ids_t;
+
+/*
* The maximum size of a SID in string format
*/
#define SMB_SID_STRSZ 256
@@ -225,7 +250,7 @@
smb_sid_t *smb_sid_dup(smb_sid_t *);
smb_sid_t *smb_sid_splice(smb_sid_t *, uint32_t);
int smb_sid_getrid(smb_sid_t *, uint32_t *);
-int smb_sid_split(smb_sid_t *, uint32_t *);
+smb_sid_t *smb_sid_split(smb_sid_t *, uint32_t *);
boolean_t smb_sid_cmp(smb_sid_t *, smb_sid_t *);
boolean_t smb_sid_islocal(smb_sid_t *);
boolean_t smb_sid_indomain(smb_sid_t *, smb_sid_t *);
@@ -235,6 +260,8 @@
smb_sid_t *smb_sid_fromstr(char *);
char *smb_sid_type2str(uint16_t);
+void smb_ids_free(smb_ids_t *);
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/smbsrv/smb_token.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_token.h Sun Feb 01 19:44:54 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.
*/
@@ -29,6 +29,7 @@
#include <smbsrv/netrauth.h>
#include <smbsrv/smb_privilege.h>
#include <smbsrv/smb_sid.h>
+#include <smbsrv/smb_xdr.h>
#ifdef __cplusplus
extern "C" {
@@ -51,40 +52,8 @@
* used when access is requested to an object by comparing this
* information with the DACL in the object's security descriptor.
*
- * Only group attributes are defined. No user attributes defined.
- */
-
-#define SE_GROUP_MANDATORY 0x00000001
-#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002
-#define SE_GROUP_ENABLED 0x00000004
-#define SE_GROUP_OWNER 0x00000008
-#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010
-#define SE_GROUP_LOGON_ID 0xC0000000
-
-typedef struct smb_sid_attrs {
- uint32_t attrs;
- smb_sid_t *sid;
-} smb_sid_attrs_t;
-
-/*
- * smb_id_t consists of both the Windows security identifier
- * and its corresponding POSIX/ephemeral ID.
- */
-typedef struct smb_id {
- smb_sid_attrs_t i_sidattr;
- uid_t i_id;
-} smb_id_t;
-
-/*
- * Windows groups (each group SID is associated with a POSIX/ephemeral
- * gid.
- */
-typedef struct smb_win_grps {
- uint16_t wg_count;
- smb_id_t wg_groups[ANY_SIZE_ARRAY];
-} smb_win_grps_t;
-
-/*
+ * There should be one unique token per user per session per client.
+ *
* Access Token Flags
*
* SMB_ATF_GUEST Token belongs to guest user
@@ -106,80 +75,26 @@
* It consists of the primary and supplementary POSIX groups.
*/
typedef struct smb_posix_grps {
- uint32_t pg_ngrps;
- gid_t pg_grps[ANY_SIZE_ARRAY];
+ uint32_t pg_ngrps;
+ gid_t pg_grps[ANY_SIZE_ARRAY];
} smb_posix_grps_t;
-/*
- * Token Structure.
- *
- * This structure contains information of a user. There should be one
- * unique token per user per session per client. The information
- * provided will either give or deny access to shares, files or folders.
- */
typedef struct smb_token {
- smb_id_t *tkn_user;
- smb_id_t *tkn_owner;
- smb_id_t *tkn_primary_grp;
- smb_win_grps_t *tkn_win_grps;
- smb_privset_t *tkn_privileges;
- char *tkn_account_name;
- char *tkn_domain_name;
- uint32_t tkn_flags;
- uint32_t tkn_audit_sid;
+ smb_id_t tkn_user;
+ smb_id_t tkn_owner;
+ smb_id_t tkn_primary_grp;
+ smb_ids_t tkn_win_grps;
+ smb_privset_t *tkn_privileges;
+ char *tkn_account_name;
+ char *tkn_domain_name;
+ uint32_t tkn_flags;
+ uint32_t tkn_audit_sid;
smb_session_key_t *tkn_session_key;
smb_posix_grps_t *tkn_posix_grps;
} smb_token_t;
-/*
- * Information returned by an RPC call is allocated on an internal heap
- * which is deallocated before returning from the interface call. The
- * smb_userinfo structure provides a useful common mechanism to get the
- * information back to the caller. It's like a compact access token but
- * only parts of it are filled in by each RPC so the content is call
- * specific.
- */
-typedef struct smb_rid_attrs {
- uint32_t rid;
- uint32_t attributes;
-} smb_rid_attrs_t;
-
-#define SMB_UINFO_FLAG_ANON 0x01
-#define SMB_UINFO_FLAG_LADMIN 0x02 /* Local admin */
-#define SMB_UINFO_FLAG_DADMIN 0x04 /* Domain admin */
-#define SMB_UINFO_FLAG_ADMIN (SMB_UINFO_FLAG_LADMIN | SMB_UINFO_FLAG_DADMIN)
-
-/*
- * This structure is mainly used where there's some
- * kind of user related interaction with a domain
- * controller via different RPC calls.
- */
-typedef struct smb_userinfo {
- uint16_t sid_name_use;
- uint32_t rid;
- uint32_t primary_group_rid;
- char *name;
- char *domain_name;
- smb_sid_t *domain_sid;
- uint32_t n_groups;
- smb_rid_attrs_t *groups;
- uint32_t n_other_grps;
- smb_sid_attrs_t *other_grps;
- smb_session_key_t *session_key;
-
- smb_sid_t *user_sid;
- smb_sid_t *pgrp_sid;
- uint32_t flags;
-} smb_userinfo_t;
-
/* XDR routines */
-extern bool_t xdr_smb_session_key_t();
extern bool_t xdr_netr_client_t();
-extern bool_t xdr_smb_sid_t();
-extern bool_t xdr_smb_sid_attrs_t();
-extern bool_t xdr_smb_id_t();
-extern bool_t xdr_smb_win_grps_t();
-extern bool_t xdr_smb_posix_grps_t();
extern bool_t xdr_smb_token_t();
--- a/usr/src/uts/common/smbsrv/smb_vops.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_vops.h Sun Feb 01 19:44:54 2009 -0700
@@ -19,15 +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_VOPS_H
#define _SMBSRV_SMB_VOPS_H
-#pragma ident "@(#)smb_vops.h 1.9 08/08/07 SMI"
-
/*
* Common file system interfaces and definitions.
*/
@@ -56,80 +54,7 @@
#define SMB_STREAM_PREFIX_LEN (sizeof (SMB_STREAM_PREFIX) - 1)
#define SMB_SHORTNAMELEN 14
-#define SMB_EOF 0x7FFFFFFF
-
-/*
- * SMB_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
- * VOP_READDIR. Its value is the size of the maximum possible edirent_t
- * for solaris. The EDIRENT_RECLEN macro returns the size of edirent_t
- * required for a given name length. MAXNAMELEN is the maximum
- * filename length allowed in Solaris. The first two EDIRENT_RECLEN()
- * macros are to allow for . and .. entries -- just a minor tweak to try
- * and guarantee that buffer we give to VOP_READDIR will be large enough
- * to hold ., .., and the largest possible solaris edirent_t.
- *
- * This bufsize will also be used when reading dirent64_t entries.
- */
-
-#define SMB_MINLEN_RDDIR_BUF \
- (EDIRENT_RECLEN(1) + EDIRENT_RECLEN(2) + EDIRENT_RECLEN(MAXNAMELEN))
-
-/*
- * DP_TO_EDP
- *
- * Fill in an edirent_t structure with information from a dirent64_t.
- * This allows the use of an edirent_t in code where both edirent_t's
- * and dirent64_t's are manipulated.
- */
-
-#define DP_TO_EDP(dp, edp) \
-{ \
- ASSERT((dp)); \
- ASSERT((edp)); \
- (edp)->ed_ino = (dp)->d_ino; \
- (edp)->ed_off = (dp)->d_off; \
- (edp)->ed_eflags = 0; \
- (edp)->ed_reclen = (dp)->d_reclen; \
- (void) strlcpy((edp)->ed_name, (dp)->d_name, MAXNAMELEN); \
-}
-
-/*
- * DP_ADVANCE
- *
- * In readdir operations, advance to read the next entry in a buffer
- * returned from VOP_READDIR. The entries are of type dirent64_t.
- */
-
-#define DP_ADVANCE(dp, dirbuf, numbytes) \
-{ \
- ASSERT((dp)); \
- if ((dp)->d_reclen == 0) { \
- (dp) = NULL; \
- } else { \
- (dp) = (dirent64_t *)((char *)(dp) + (dp)->d_reclen); \
- if ((dp) >= (dirent64_t *)((dirbuf) + (numbytes))) \
- (dp) = NULL; \
- } \
-}
-
-/*
- * EDP_ADVANCE
- *
- * In readdir operations, advance to read the next entry in a buffer
- * returned from VOP_READDIR. The entries are of type edirent_t.
- */
-
-#define EDP_ADVANCE(edp, dirbuf, numbytes) \
-{ \
- ASSERT((edp)); \
- if ((edp)->ed_reclen == 0) { \
- (edp) = NULL; \
- } else { \
- (edp) = (edirent_t *)((char *)(edp) + (edp)->ed_reclen);\
- if ((edp) >= (edirent_t *)((dirbuf) + (numbytes))) \
- (edp) = NULL; \
- } \
-}
+#define SMB_MAXDIRSIZE 0x7FFFFFFF
struct smb_node;
struct smb_request;
@@ -173,11 +98,6 @@
SMB_AT_ATIME|SMB_AT_MTIME|SMB_AT_CTIME|SMB_AT_RDEV|\
SMB_AT_BLKSIZE|SMB_AT_NBLOCKS|SMB_AT_SEQ|SMB_AT_SMB)
-struct fs_stream_info {
- char name[MAXPATHLEN];
- uint64_t size;
-};
-
int fhopen(const struct smb_node *, int);
int smb_vop_init(void);
@@ -200,19 +120,14 @@
int smb_vop_mkdir(vnode_t *, char *, smb_attr_t *, vnode_t **, int, cred_t *,
vsecattr_t *);
int smb_vop_rmdir(vnode_t *, char *, int, cred_t *);
-int smb_vop_readdir(vnode_t *, uint32_t *, char *, int *, ino64_t *, vnode_t **,
- char *, int, cred_t *);
+int smb_vop_readdir(vnode_t *, uint32_t, void *, int *, int *, cred_t *);
int smb_vop_commit(vnode_t *, cred_t *);
-int smb_vop_getdents(struct smb_node *, uint32_t *, uint64_t *, int32_t *,
- char *, char *, uint32_t, struct smb_request *, cred_t *);
int smb_vop_statfs(vnode_t *, struct statvfs64 *, cred_t *);
int smb_vop_stream_lookup(vnode_t *, char *, vnode_t **, char *, vnode_t **,
int, vnode_t *, cred_t *);
int smb_vop_stream_create(vnode_t *, char *, smb_attr_t *, vnode_t **,
vnode_t **, int, cred_t *);
int smb_vop_stream_remove(vnode_t *, char *, int, cred_t *);
-int smb_vop_stream_readdir(vnode_t *, uint32_t *, struct fs_stream_info *,
- vnode_t **, vnode_t **, int, cred_t *);
int smb_vop_lookup_xattrdir(vnode_t *, vnode_t **, int, cred_t *);
int smb_vop_traverse_check(vnode_t **);
--- a/usr/src/uts/common/smbsrv/smb_xdr.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smb_xdr.h Sun Feb 01 19:44:54 2009 -0700
@@ -32,6 +32,7 @@
#include <rpc/xdr.h>
#include <sys/param.h>
+#include <smbsrv/smbinfo.h>
typedef struct smb_dr_kshare {
int32_t k_op;
@@ -101,7 +102,7 @@
char *oc_account;
uint16_t oc_workstation_len;
char *oc_workstation;
- uint32_t oc_ipaddr;
+ smb_inaddr_t oc_ipaddr;
int32_t oc_native_os;
int64_t oc_logon_time;
uint32_t oc_flags;
@@ -117,6 +118,7 @@
extern bool_t xdr_smb_dr_bytes_t(XDR *, smb_dr_bytes_t *);
extern bool_t xdr_smb_dr_ulist_t(XDR *, smb_dr_ulist_t *);
extern bool_t xdr_smb_dr_kshare_t(XDR *, smb_dr_kshare_t *);
+extern bool_t xdr_smb_inaddr_t(XDR *, smb_inaddr_t *);
int smb_opipe_hdr_encode(smb_opipe_hdr_t *, uint8_t *, uint32_t);
int smb_opipe_hdr_decode(smb_opipe_hdr_t *, uint8_t *, uint32_t);
--- a/usr/src/uts/common/smbsrv/smbinfo.h Sun Feb 01 15:33:03 2009 -0800
+++ b/usr/src/uts/common/smbsrv/smbinfo.h Sun Feb 01 19:44:54 2009 -0700
@@ -28,6 +28,8 @@
#include <sys/types.h>
#include <smbsrv/netbios.h>
+#include <netinet/in.h>
+#include <smbsrv/smb_inet.h>
#ifdef __cplusplus
extern "C" {
@@ -114,6 +116,7 @@
int32_t skc_oplock_enable;
int32_t skc_sync_enable;
int32_t skc_secmode;
+ int32_t skc_ipv6_enable;
char skc_nbdomain[NETBIOS_NAME_SZ];
char skc_fqdn[SMB_PI_MAX_DOMAIN];
char skc_hostname[SMB_PI_MAX_HOST];
--- a/usr/src/uts/common/smbsrv/smbtrans.h Sun Feb 01 15:33:03 2009 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SMBSRV_SMBTRANS_H
-#define _SMBSRV_SMBTRANS_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <sys/param.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Note that name can be variable length; therefore, it has to
- * stay last.
- */
-typedef struct smb_dent_info {
- uint32_t cookie;
- smb_attr_t attr;
- struct smb_node *snode;
- char name83[14];
- char shortname[14];
- char name[1];
-} smb_dent_info_t;
-
-#define SMB_MAX_DENT_INFO_SIZE (sizeof (smb_dent_info_t) + MAXNAMELEN - 1)
-#define SMB_MAX_DENTS_BUF_SIZE (64 * 1024) /* 64k */
-#define SMB_MAX_DENTS_IOVEC (SMB_MAX_DENTS_BUF_SIZE / SMB_MAX_DENT_INFO_SIZE)
-
-typedef struct smb_dent_info_hdr {
- struct smb_request *sr;
- char *pattern;
- unsigned short sattr;
- struct uio uio;
- struct iovec iov[SMB_MAX_DENTS_IOVEC];
-} smb_dent_info_hdr_t;
-
-int smb_get_dents(struct smb_request *sr, uint32_t *cookie,
- struct smb_node *dir_snode, unsigned int wildcards,
- smb_dent_info_hdr_t *ihdr, int *more);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SMBSRV_SMBTRANS_H */