diff options
Diffstat (limited to 'usr/src')
170 files changed, 8473 insertions, 9564 deletions
diff --git a/usr/src/cmd/dfs.cmds/sharemgr/commands.c b/usr/src/cmd/dfs.cmds/sharemgr/commands.c index 3ba5cc892b..f6e0f24d3f 100644 --- a/usr/src/cmd/dfs.cmds/sharemgr/commands.c +++ b/usr/src/cmd/dfs.cmds/sharemgr/commands.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2973,7 +2973,7 @@ sa_set_share(sa_handle_t handle, int flags, int argc, char *argv[]) int c; int ret = SA_OK; sa_group_t group, sharegroup; - sa_share_t share; + sa_share_t share = NULL; sa_resource_t resource = NULL; char *sharepath = NULL; char *description = NULL; @@ -3107,9 +3107,10 @@ sa_set_share(sa_handle_t handle, int flags, int argc, char *argv[]) share = sa_find_share(handle, sharepath); } else if (rsrcname != NULL) { resource = sa_find_resource(handle, rsrc); - if (resource != NULL) { + if (resource != NULL) share = sa_get_resource_parent(resource); - } + else + ret = SA_NO_SUCH_RESOURCE; } if (share != NULL) { sharegroup = sa_get_parent_group(share); @@ -3191,9 +3192,22 @@ sa_set_share(sa_handle_t handle, int flags, int argc, char *argv[]) break; } } else { - (void) printf(gettext("Share path \"%s\" not found\n"), - sharepath); - ret = SA_NO_SUCH_PATH; + switch (ret) { + case SA_NO_SUCH_RESOURCE: + (void) printf(gettext("Resource \"%s\" not found\n"), + rsrcname); + break; + default: + if (sharepath != NULL) { + (void) printf( + gettext("Share path \"%s\" not found\n"), + sharepath); + ret = SA_NO_SUCH_PATH; + } else { + (void) printf(gettext("Set failed: %s\n"), + sa_errorstr(ret)); + } + } } return (ret); diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c index d8cca22f4f..77a6095bbf 100644 --- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c +++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -203,7 +203,6 @@ smb_information(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%sAnnounce Quota\n", (smb_info.si.skc_announce_quota) ? "" : "Do Not "); mdb_printf("Security Mode %d\n", smb_info.si.skc_secmode); - mdb_printf("LM Level %d\n", smb_info.si.skc_lmlevel); mdb_printf("Domain %s\n", smb_info.si.skc_resource_domain); mdb_printf("Hostname %s\n", smb_info.si.skc_hostname); mdb_printf("Comment %s\n", smb_info.si.skc_system_comment); diff --git a/usr/src/cmd/smbsrv/dtrace/msrpc.d b/usr/src/cmd/smbsrv/dtrace/msrpc.d index abf6497980..ce352a7588 100755 --- a/usr/src/cmd/smbsrv/dtrace/msrpc.d +++ b/usr/src/cmd/smbsrv/dtrace/msrpc.d @@ -20,7 +20,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -85,6 +85,18 @@ * trace:entry MO 02 .. sec_addr.port_spec[11] put 1@37 = 0 {00} */ +BEGIN +{ + printf("MSRPC Trace Started"); + printf("\n\n"); +} + +END +{ + printf("MSRPC Trace Ended"); + printf("\n\n"); +} + /* * SmbSessionSetupX, SmbLogoffX * SmbTreeConnect, SmbTreeDisconnect @@ -97,16 +109,24 @@ smb_com_session_setup_andx:entry, smb_com_logoff_andx:entry, smb_tree_connect:return, smb_tree_disconnect:entry, -smb_tree_disconnect:return +smb_tree_disconnect:return, +smb_winpipe_open:entry, +smb_winpipe_call:entry, +smb_winpipe_upcall:entry, +door_ki_upcall:entry { } smb_com_session_setup_andx:return, smb_session*:return, smb_user*:return, -smb_tree*:return +smb_tree*:return, +smb_winpipe_open:return, +smb_winpipe_call:return, +smb_winpipe_upcall:return, +door_ki_upcall:return { - printf("rc=%d", arg1); + printf("rc=0x%08x", arg1); } sdt:smbsrv::smb-sessionsetup-clntinfo @@ -131,22 +151,12 @@ smb_com_logoff_andx:return /* * Raise error functions (no return). */ -smbsr_raise_error:entry -{ - printf("class=%d code=%d", arg1, arg2); -} - -smbsr_raise_cifs_error:entry +smbsr_error:entry { printf("status=0x%08x class=%d, code=%d", arg1, arg2, arg3); } -smbsr_raise_nt_error:entry -{ - printf("error=0x%08x", arg1); -} - -smbsr_raise_errno:entry +smbsr_errno:entry { printf("errno=%d", arg1); } @@ -356,7 +366,7 @@ pid$target::smbrdr_*:return { } -pid$target::mlsvc_tree_connect:entry +pid$target::smbrdr_tree_connect:entry { printf("%s %s %s", copyinstr(arg0), @@ -377,7 +387,7 @@ pid$target::mlsvc_close_pipe:entry { } -pid$target::mlsvc_tree_connect:return, +pid$target::smbrdr_tree_connect:return, pid$target::mlsvc_open_pipe:return, pid$target::mlsvc_close_pipe:return { diff --git a/usr/src/cmd/smbsrv/dtrace/stype.d b/usr/src/cmd/smbsrv/dtrace/stype.d index 19fef52dbe..53968091bb 100755 --- a/usr/src/cmd/smbsrv/dtrace/stype.d +++ b/usr/src/cmd/smbsrv/dtrace/stype.d @@ -22,7 +22,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,22 +60,12 @@ smb_com_logoff_andx:return /* * Raise error functions (no return). */ -smbsr_raise_error:entry -{ - printf("class=%d code=%d", arg1, arg2); -} - -smbsr_raise_cifs_error:entry +smbsr_error:entry { printf("status=0x%08x class=%d, code=%d", arg1, arg2, arg3); } -smbsr_raise_nt_error:entry -{ - printf("error=0x%08x", arg1); -} - -smbsr_raise_errno:entry +smbsr_errno:entry { printf("errno=%d", arg1); } diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c index 17cb3b8300..adeac3cb6a 100644 --- a/usr/src/cmd/smbsrv/smbadm/smbadm.c +++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,6 @@ #include <libgen.h> #include <smbsrv/libsmb.h> -#include <smbsrv/libmlsvc.h> typedef enum { HELP_ADD_MEMBER, @@ -403,9 +402,7 @@ smbadm_list(int argc, char **argv) return (1); } - (void) printf(gettext("%s name: %s\n"), - modename, resource_domain); - + (void) printf(gettext("%s name: %s\n"), modename, resource_domain); return (0); } @@ -420,7 +417,7 @@ smbadm_group_create(int argc, char **argv) char *gname = NULL; char *desc = NULL; char option; - uint32_t status; + int status; while ((option = getopt(argc, argv, "d:")) != -1) { switch (option) { @@ -441,19 +438,19 @@ smbadm_group_create(int argc, char **argv) if (getgrnam(gname) == NULL) { (void) fprintf(stderr, - gettext("failed to get the Solaris group\n")); + gettext("failed to get the Solaris group '%s'\n"), gname); (void) fprintf(stderr, - gettext("use 'groupadd' to add the Solaris group\n")); + gettext("use 'groupadd' to add '%s'\n"), gname); return (1); } - status = smb_group_add(gname, desc); - if (status != NT_STATUS_SUCCESS) { + status = smb_lgrp_add(gname, desc); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to create the group (%s)\n"), - xlate_nt_status(status)); + smb_lgrp_strerror(status)); } else { - (void) printf(gettext("Successfully created group '%s'\n"), + (void) printf(gettext("'%s' created.\n"), gname); } @@ -466,38 +463,21 @@ smbadm_group_create(int argc, char **argv) * Dump group members details. */ static void -smbadm_group_dump_members(char *gname) +smbadm_group_dump_members(smb_gsid_t *members, int num) { - ntgrp_member_list_t *members = NULL; - int mem_cnt = 0; - int offset = 0; - uint32_t status; + char sidstr[NT_SID_FMTBUF_SIZE]; int i; - status = smb_group_member_count(gname, &mem_cnt); - if (mem_cnt < 0) { - (void) fprintf(stderr, - gettext("failed to get the group members (%s)\n"), - xlate_nt_status(status)); - } - - if (mem_cnt == 0) { + if (num == 0) { (void) printf(gettext("\tNo members\n")); return; } (void) printf(gettext("\tMembers:\n")); - while (smb_group_member_list(gname, offset, &members) == 0) { - if (members == NULL) - break; - - for (i = 0; i < members->cnt; i++) - (void) printf(gettext("\t\t%s\n"), members->members[i]); - - offset += members->cnt; - smb_group_free_memberlist(members, 0); - if (offset >= mem_cnt) - break; + for (i = 0; i < num; i++) { + (void) smb_lookup_sid(members[i].gs_sid, sidstr, + sizeof (sidstr)); + (void) printf(gettext("\t\t%s\n"), sidstr); } } @@ -507,39 +487,34 @@ smbadm_group_dump_members(char *gname) * Dump group privilege details. */ static void -smbadm_group_dump_privs(char *gname, ntpriv_list_t *privs) +smbadm_group_dump_privs(smb_privset_t *privs) { - int privcnt = 0; - uint32_t privval; - char *name = NULL; + smb_privinfo_t *pinfo; + char *pstatus; int i; (void) printf(gettext("\tPrivileges: \n")); - for (i = 0; i < privs->cnt; i++) { - name = privs->privs[i]->name; - if (name == NULL) + for (i = 0; i < privs->priv_cnt; i++) { + pinfo = smb_priv_getbyvalue(privs->priv[i].luid.lo_part); + if ((pinfo == NULL) || (pinfo->flags & PF_PRESENTABLE) == 0) continue; - if (smb_group_priv_get(gname, privs->privs[i]->id, - &privval) != 0) { - continue; - } - - if (privval == SE_PRIVILEGE_ENABLED) { - (void) printf(gettext("\t\t%s: On\n"), name); - } else if (privval == SE_PRIVILEGE_DISABLED) { - (void) printf(gettext("\t\t%s: Off\n"), name); - } else { - (void) printf(gettext("\t\t%s: %d\n"), - name, privval); + switch (privs->priv[i].attrs) { + case SE_PRIVILEGE_ENABLED: + pstatus = "On"; + break; + case SE_PRIVILEGE_DISABLED: + pstatus = "Off"; + break; + default: + pstatus = "Unknown"; + break; } - - name = NULL; - privcnt++; + (void) printf(gettext("\t\t%s: %s\n"), pinfo->name, pstatus); } - if (privcnt == 0) + if (privs->priv_cnt == 0) (void) printf(gettext("\t\tNo privileges\n")); } @@ -548,41 +523,21 @@ smbadm_group_dump_privs(char *gname, ntpriv_list_t *privs) * * Dump group details. */ -static int -smbadm_group_dump(ntgrp_list_t *list, boolean_t show_mem, boolean_t show_privs) +static void +smbadm_group_dump(smb_group_t *grp, boolean_t show_mem, boolean_t show_privs) { - ntpriv_list_t *privs = NULL; - char *gname; - uint32_t status; - int i; + char sidstr[NT_SID_FMTBUF_SIZE]; - if (show_privs) { - if ((status = smb_group_priv_list(&privs)) != 0) { - (void) fprintf(stderr, - gettext("failed to get privileges (%s)\n"), - xlate_nt_status(status)); - return (1); - } - } + (void) printf(gettext("%s (%s)\n"), grp->sg_name, grp->sg_cmnt); - for (i = 0; i < list->cnt; i++) { - gname = list->groups[i].name; + nt_sid_format2(grp->sg_id.gs_sid, sidstr); + (void) printf(gettext("\tSID: %s\n"), sidstr); - (void) printf(gettext("%s (%s)\n"), gname, - list->groups[i].desc); - (void) printf(gettext("\tType: %s, Attr: %X\n"), - list->groups[i].type, list->groups[i].attr); - (void) printf(gettext("\tSID: %s\n"), - list->groups[i].sid); - - if (show_privs) - smbadm_group_dump_privs(gname, privs); - - if (show_mem) - smbadm_group_dump_members(list->groups[i].name); - } + if (show_privs) + smbadm_group_dump_privs(grp->sg_privs); - return (0); + if (show_mem) + smbadm_group_dump_members(grp->sg_members, grp->sg_nmembers); } /* @@ -593,14 +548,12 @@ static int smbadm_group_show(int argc, char **argv) { char *gname = NULL; - int cnt = 0; - int offset = 0; boolean_t show_privs; boolean_t show_members; char option; - uint32_t status; - ntgrp_list_t *list = NULL; - int ret = 0; + int status; + smb_group_t grp; + smb_giter_t gi; show_privs = show_members = B_FALSE; @@ -622,47 +575,44 @@ smbadm_group_show(int argc, char **argv) if (optind >= argc || gname == NULL || *gname == '\0') gname = "*"; - status = smb_group_count(&cnt); - if ((status != NT_STATUS_SUCCESS) || (cnt < 0)) { - (void) fprintf(stderr, - gettext("failed to get the number of group(s) (%s)\n"), - xlate_nt_status(status)); - return (1); - } - - while ((offset < cnt)) { - status = smb_group_list(offset, &list, gname, 0); - if (status != NT_STATUS_SUCCESS) { + if (strcmp(gname, "*")) { + status = smb_lgrp_getbyname(gname, &grp); + if (status == SMB_LGRP_SUCCESS) { + smbadm_group_dump(&grp, show_members, show_privs); + smb_lgrp_free(&grp); + } else { (void) fprintf(stderr, - gettext("failed to get the group(s) (%s)\n"), - xlate_nt_status(status)); - return (1); + gettext("failed to find '%s' (%s)\n"), + gname, smb_lgrp_strerror(status)); } + return (status); + } - if ((list == NULL) || (list->cnt <= 0)) - break; - - ret = smbadm_group_dump(list, show_members, show_privs); - if (ret) - break; + status = smb_lgrp_iteropen(&gi); + if (status != SMB_LGRP_SUCCESS) { + (void) fprintf(stderr, + gettext("failed to list groups (%s)\n"), + smb_lgrp_strerror(status)); + return (status); + } - offset += list->cnt; - smb_group_free_list(list, 0); - list = NULL; + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + smbadm_group_dump(&grp, show_members, show_privs); + smb_lgrp_free(&grp); } + smb_lgrp_iterclose(&gi); - return (ret); + return (0); } /* * smbadm_group_delete - * */ static int smbadm_group_delete(int argc, char **argv) { - uint32_t status; char *gname = NULL; + int status; gname = argv[optind]; if (optind >= argc || gname == NULL || *gname == '\0') { @@ -670,13 +620,13 @@ smbadm_group_delete(int argc, char **argv) smbadm_usage(B_FALSE); } - status = smb_group_delete(gname); - if (status != NT_STATUS_SUCCESS) { + status = smb_lgrp_delete(gname); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to delete the group (%s)\n"), - xlate_nt_status(status)); + smb_lgrp_strerror(status)); } else { - (void) printf(gettext("Successfully deleted group '%s'\n"), + (void) printf(gettext("'%s' deleted.\n"), gname); } @@ -685,14 +635,13 @@ smbadm_group_delete(int argc, char **argv) /* * smbadm_group_rename - * */ static int smbadm_group_rename(int argc, char **argv) { char *gname = NULL; char *ngname = NULL; - uint32_t status; + int status; gname = argv[optind]; if (optind++ >= argc || gname == NULL || *gname == '\0') { @@ -706,22 +655,26 @@ smbadm_group_rename(int argc, char **argv) smbadm_usage(B_FALSE); } - if (getgrnam(gname) == NULL) { + if (getgrnam(ngname) == NULL) { (void) fprintf(stderr, - gettext("failed to get the Solaris group\n")); + gettext("failed to get the Solaris group '%s'\n"), ngname); (void) fprintf(stderr, - gettext("use 'groupadd' to add the Solaris group\n")); + gettext("use 'groupadd' to add '%s'\n"), ngname); return (1); } - status = smb_group_modify(gname, ngname, NULL); - if (status != NT_STATUS_SUCCESS) { - (void) fprintf(stderr, - gettext("failed to modify the group (%s)\n"), - xlate_nt_status(status)); + status = smb_lgrp_rename(gname, ngname); + if (status != SMB_LGRP_SUCCESS) { + if (status == SMB_LGRP_EXISTS) + (void) fprintf(stderr, + gettext("failed to rename '%s' (%s already " + "exists)\n"), gname, ngname); + else + (void) fprintf(stderr, + gettext("failed to rename '%s' (%s)\n"), gname, + smb_lgrp_strerror(status)); } else { - (void) printf(gettext("Successfully modified " - "group '%s'\n"), gname); + (void) printf(gettext("'%s' renamed to '%s'\n"), gname, ngname); } return (status); @@ -755,14 +708,8 @@ smbadm_group_setprop(int argc, char **argv) smbadm_usage(B_FALSE); } - ret = smbadm_prop_parse(optarg, &props[pcnt++]); - if (ret) { - if (ret == 1) - exit(1); - - if (ret == 2) - smbadm_usage(B_FALSE); - } + if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) + smbadm_usage(B_FALSE); break; default: @@ -821,14 +768,8 @@ smbadm_group_getprop(int argc, char **argv) smbadm_usage(B_FALSE); } - ret = smbadm_prop_parse(optarg, &props[pcnt++]); - if (ret) { - if (ret == 1) - exit(1); - - if (ret == 2) - smbadm_usage(B_FALSE); - } + if (smbadm_prop_parse(optarg, &props[pcnt++]) != 0) + smbadm_usage(B_FALSE); break; default: @@ -873,7 +814,8 @@ smbadm_group_addmember(int argc, char **argv) char *gname = NULL; char **mname; char option; - uint32_t status; + smb_gsid_t msid; + int status; int mcnt = 0; int ret = 0; int i; @@ -916,16 +858,25 @@ smbadm_group_addmember(int argc, char **argv) if (mname[i] == NULL) continue; - status = smb_group_member_add(gname, mname[i]); - if (status != NT_STATUS_SUCCESS) { + if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { + (void) fprintf(stderr, + gettext("failed to add %s " + "(could not obtain the SID)\n"), + mname[i]); + continue; + } + + status = smb_lgrp_add_member(gname, msid.gs_sid, msid.gs_type); + free(msid.gs_sid); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to add %s (%s)\n"), - mname[i], xlate_nt_status(status)); + mname[i], smb_lgrp_strerror(status)); ret = 1; - } - else - (void) printf(gettext("Successfully added %s to %s\n"), + } else { + (void) printf(gettext("'%s' is now a member of '%s'\n"), mname[i], gname); + } } free(mname); @@ -941,7 +892,8 @@ smbadm_group_delmember(int argc, char **argv) char *gname = NULL; char **mname; char option; - uint32_t status; + smb_gsid_t msid; + int status; int mcnt = 0; int ret = 0; int i; @@ -983,15 +935,24 @@ smbadm_group_delmember(int argc, char **argv) if (mname[i] == NULL) continue; - status = smb_group_member_remove(gname, mname[i]); - if (status != NT_STATUS_SUCCESS) { + if (smb_lookup_name(mname[i], &msid) != NT_STATUS_SUCCESS) { + (void) fprintf(stderr, + gettext("failed to remove %s " + "(could not obtain the SID)\n"), + mname[i]); + continue; + } + + status = smb_lgrp_del_member(gname, msid.gs_sid, msid.gs_type); + free(msid.gs_sid); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to remove %s (%s)\n"), - mname[i], xlate_nt_status(status)); + mname[i], smb_lgrp_strerror(status)); ret = 1; } else { (void) printf( - gettext("Successfully removed %s from %s\n"), + gettext("'%s' has been removed from %s\n"), mname[i], gname); } } @@ -1045,6 +1006,7 @@ smbadm_user_enable(int argc, char **argv) int main(int argc, char **argv) { + int ret; int i; (void) malloc(0); /* satisfy libumem dependency */ @@ -1087,7 +1049,24 @@ main(int argc, char **argv) smbadm_usage(B_TRUE); } - return (curcmd->func(argc - 1, &argv[1])); + if (smb_idmap_start() != 0) { + (void) fprintf(stderr, + gettext("failed to contact idmap service")); + return (1); + } + + if ((ret = smb_lgrp_start()) != SMB_LGRP_SUCCESS) { + (void) fprintf(stderr, + gettext("failed to initialize (%s)"), + smb_lgrp_strerror(ret)); + smb_idmap_stop(); + return (1); + } + + ret = curcmd->func(argc - 1, &argv[1]); + smb_lgrp_stop(); + smb_idmap_stop(); + return (ret); } } @@ -1167,13 +1146,13 @@ smbadm_prop_gethandle(char *pname) static int smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) { - uint32_t status; + int status; - status = smb_group_modify(gname, gname, prop->p_value); - if (status != NT_STATUS_SUCCESS) { + status = smb_lgrp_setcmnt(gname, prop->p_value); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to modify the group description (%s)\n"), - xlate_nt_status(status)); + smb_lgrp_strerror(status)); return (1); } @@ -1186,50 +1165,44 @@ smbadm_setprop_desc(char *gname, smbadm_prop_t *prop) static int smbadm_getprop_desc(char *gname, smbadm_prop_t *prop) { - uint32_t status; - ntgrp_list_t *list = NULL; + char *cmnt = NULL; + int status; - status = smb_group_list(0, &list, gname, 0); - if (status != NT_STATUS_SUCCESS) { + status = smb_lgrp_getcmnt(gname, &cmnt); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, - gettext("failed to get the %s (%s)\n"), - prop->p_name, xlate_nt_status(status)); - return (1); - } - - if ((list == NULL) || (list->cnt <= 0)) { - (void) fprintf(stderr, gettext("%s: no such group\n"), gname); + gettext("failed to get the group description (%s)\n"), + smb_lgrp_strerror(status)); return (1); } - (void) printf(gettext("\t%s: %s\n"), prop->p_name, - list->groups[0].desc); - smb_group_free_list(list, 0); + (void) printf(gettext("\t%s: %s\n"), prop->p_name, cmnt); + free(cmnt); return (0); } static int -smbadm_group_setpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop) +smbadm_group_setpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) { - uint32_t priv_attr; - uint32_t status; + boolean_t enable; + int status; int ret; if (strcasecmp(prop->p_value, "on") == 0) { (void) printf(gettext("Enabling %s privilege "), prop->p_name); - priv_attr = SE_PRIVILEGE_ENABLED; + enable = B_TRUE; } else { (void) printf(gettext("Disabling %s privilege "), prop->p_name); - priv_attr = SE_PRIVILEGE_DISABLED; + enable = B_FALSE; } - status = smb_group_priv_set(gname, priv_id, priv_attr); - - if (status == NT_STATUS_SUCCESS) { + status = smb_lgrp_setpriv(gname, priv_id, enable); + if (status == SMB_LGRP_SUCCESS) { (void) printf(gettext("succeeded\n")); ret = 0; } else { - (void) printf(gettext("failed: %s\n"), xlate_nt_status(status)); + (void) printf(gettext("failed: %s\n"), + smb_lgrp_strerror(status)); ret = 1; } @@ -1237,24 +1210,20 @@ smbadm_group_setpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop) } static int -smbadm_group_getpriv(char *gname, uint32_t priv_id, smbadm_prop_t *prop) +smbadm_group_getpriv(char *gname, uint8_t priv_id, smbadm_prop_t *prop) { - uint32_t priv_attr; - uint32_t status; + boolean_t enable; + int status; - status = smb_group_priv_get(gname, priv_id, &priv_attr); - if (status != NT_STATUS_SUCCESS) { + status = smb_lgrp_getpriv(gname, priv_id, &enable); + if (status != SMB_LGRP_SUCCESS) { (void) fprintf(stderr, gettext("failed to get %s (%s)\n"), - prop->p_name, xlate_nt_status(status)); + prop->p_name, smb_lgrp_strerror(status)); return (1); } - if (priv_attr == SE_PRIVILEGE_ENABLED) - (void) printf(gettext("\t%s: %s\n"), prop->p_name, "On"); - else if (priv_attr == SE_PRIVILEGE_DISABLED) - (void) printf(gettext("\t%s: %s\n"), prop->p_name, "Off"); - else - (void) printf(gettext("\t%s: %s\n"), prop->p_name, "Unknown"); + (void) printf(gettext("\t%s: %s\n"), prop->p_name, + (enable) ? "On" : "Off"); return (0); } diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml index 879ca260a8..99b6b7c033 100644 --- a/usr/src/cmd/smbsrv/smbd/server.xml +++ b/usr/src/cmd/smbsrv/smbd/server.xml @@ -21,7 +21,7 @@ CDDL HEADER END - Copyright 2007 Sun Microsystems, Inc. All rights reserved. + Copyright 2008 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. ident "%Z%%M% %I% %E% SMI" @@ -124,10 +124,6 @@ value='solaris.smf.read.smb' /> <propval name='value_authorization' type='astring' value='solaris.smf.value.smb' /> - <propval name='rdr_ipcuser' type='astring' value='' /> - <propval name='rdr_ipcpasswd' type='astring' value='' /> - <propval name='ads_user' type='astring' value='' /> - <propval name='ads_passwd' type='astring' value='' /> <propval name='machine_passwd' type='astring' value='' /> </property_group> @@ -136,8 +132,6 @@ <stability value='Evolving' /> <propval name='value_authorization' type='astring' value='solaris.smf.value.smb' /> - <propval name='rdr_ipcmode' type='astring' - value='auth' override='true'/> <propval name='oplock_enable' type='boolean' value='false' override='true'/> <propval name='oplock_timeout' type='integer' @@ -160,8 +154,6 @@ value='' override='true'/> <propval name='srvsvc_sharesetinfo_enable' type='boolean' value='false' override='true'/> - <propval name='logr_enable' type='boolean' - value='false' override='true'/> <propval name='mlrpc_keep_alive_interval' type='integer' value='30' override='true'/> <propval name='max_bufsize' type='integer' @@ -196,24 +188,10 @@ value='' override='true'/> <propval name='lmauth_level' type='integer' value='4' override='true'/> - <propval name='msdcs_disable' type='boolean' - value='false' override='true'/> - <propval name='ads_enable' type='boolean' - value='false' override='true'/> - <propval name='ads_domain' type='astring' - value='' override='true'/> <propval name='ads_site' type='astring' value='' override='true'/> - <propval name='ads_user_container' type='astring' - value='cn=Users' override='true'/> - <propval name='ads_ip_lookup' type='boolean' - value='false' override='true'/> <propval name='ddns_enable' type='boolean' value='false' override='true'/> - <propval name='ddns_retry_cnt' type='integer' - value='3' override='true'/> - <propval name='ddns_retry_sec' type='integer' - value='2' override='true'/> </property_group> <!-- 6. Identify faults to be ignored. --> diff --git a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c index 5b1634a719..72b27a581e 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_door_ops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,7 @@ #include <synch.h> #include <strings.h> #include <smbsrv/smb_common_door.h> +#include <smbsrv/mlsvc_util.h> #include <smbsrv/libmlsvc.h> #include "smbd.h" @@ -50,33 +51,9 @@ static char *smb_dop_user_auth_logoff(char *argp, size_t arg_size, static char *smb_dop_user_list(char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_add(char *argp, size_t arg_size, +static char *smb_dop_lookup_sid(char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_delete(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_member_add(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_member_remove(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_count(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_cachesize(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_modify(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_priv_num(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_priv_list(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_priv_get(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_priv_set(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_list(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_member_list(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); -static char *smb_dop_group_member_count(char *argp, size_t arg_size, +static char *smb_dop_lookup_name(char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err); /* SMB daemon's door operation table */ @@ -87,20 +64,8 @@ smb_dr_op_t smb_doorsrv_optab[] = smb_dop_user_nonauth_logon, smb_dop_user_auth_logoff, smb_dop_user_list, - smb_dop_group_add, - smb_dop_group_delete, - smb_dop_group_member_add, - smb_dop_group_member_remove, - smb_dop_group_count, - smb_dop_group_cachesize, - smb_dop_group_modify, - smb_dop_group_priv_num, - smb_dop_group_priv_list, - smb_dop_group_priv_get, - smb_dop_group_priv_set, - smb_dop_group_list, - smb_dop_group_member_list, - smb_dop_group_member_count + smb_dop_lookup_sid, + smb_dop_lookup_name, }; /*ARGSUSED*/ @@ -330,587 +295,86 @@ smb_dop_user_list(char *argp, size_t arg_size, return (rbuf); } -/* NT Group door operations start from here */ -/*ARGSUSED*/ -static char * -smb_dop_group_add(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - ntgrp_dr_arg_t *args; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_add: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - ntstatus = nt_group_add(args->gname, args->desc); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_delete(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *gname = NULL; - char *rbuf = NULL; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((gname = smb_dr_decode_string(argp, arg_size)) == 0) { - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - ntstatus = nt_group_delete(gname); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_member_add(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - ntgrp_dr_arg_t *args; - nt_group_t *grp = NULL; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_member_add: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - grp = nt_group_getinfo(args->gname, RWLOCK_WRITER); - if (grp) { - ntstatus = nt_group_add_member_byname(args->gname, - args->member); - } else { - ntstatus = NT_STATUS_NO_SUCH_GROUP; - } - nt_group_putinfo(grp); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_member_remove(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - ntgrp_dr_arg_t *args; - nt_group_t *grp = NULL; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_member_add: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - grp = nt_group_getinfo(args->gname, RWLOCK_WRITER); - if (grp) { - ntstatus = nt_group_del_member_byname(grp, args->member); - } else { - ntstatus = NT_STATUS_NO_SUCH_GROUP; - } - nt_group_putinfo(grp); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_count(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - int num = 0; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - num = nt_group_num_groups(); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &num, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_cachesize(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - int num = 0; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - num = nt_group_cache_size(); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &num, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - return (rbuf); -} - /*ARGSUSED*/ static char * -smb_dop_group_modify(char *argp, size_t arg_size, +smb_dop_lookup_name(char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) { char *rbuf = NULL; - ntgrp_dr_arg_t *args; - nt_group_t *grp = NULL; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; + char *name = NULL; + uint32_t status; + nt_sid_t *sid; + uint16_t sid_type; + char strsid[NT_SID_FMTBUF_SIZE]; + char strres[NT_SID_FMTBUF_SIZE]; *err = SMB_DR_OP_SUCCESS; *rbufsize = 0; /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_modify: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - grp = nt_group_getinfo(args->gname, RWLOCK_WRITER); - if (grp) { - if (!args->desc) - args->desc = grp->comment; - ntstatus = nt_group_modify(args->gname, - args->newgname, args->desc); - } else { - ntstatus = NT_STATUS_NO_SUCH_GROUP; - } - nt_group_putinfo(grp); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_priv_num(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - int num = 0; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - num = smb_priv_presentable_num(); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &num, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_priv_list(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - int num = 0, i, len = 0; - uint32_t *ids = NULL; - smb_privinfo_t *priv = NULL; - ntpriv_list_t *list; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - num = smb_priv_presentable_num(); - if (num > 0) { - len = sizeof (int) + (num * sizeof (privs_t *)); - if ((ids = malloc(num * sizeof (uint32_t))) == 0) { - syslog(LOG_ERR, "smb_dop_group_priv_list:" - "cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - - if ((list = (ntpriv_list_t *)malloc(len)) == 0) { - syslog(LOG_ERR, "smb_dop_group_priv_list:" - "cannot allocate memory"); - *err = SMB_DR_OP_ERR; - free(ids); - return (NULL); - } - - list->cnt = num; - (void) smb_priv_presentable_ids(ids, num); - for (i = 0; i < num; i++) { - if ((list->privs[i] = malloc(sizeof (ntpriv_t))) == 0) { - *err = SMB_DR_OP_ERR; - free(ids); - smb_group_free_privlist(list, 1); - return (NULL); - } - bzero(list->privs[i], sizeof (ntpriv_t)); - priv = smb_priv_getbyvalue(ids[i]); - list->privs[i]->id = priv->id; - list->privs[i]->name = strdup(priv->name); - } - free(ids); - } - - if ((rbuf = smb_dr_encode_grp_privlist(SMB_DR_OP_SUCCESS, list, - rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - - smb_group_free_privlist(list, 1); - - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_priv_get(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - ntgrp_dr_arg_t *args; - uint32_t priv_attr; - nt_group_t *grp; - uint32_t retval; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_priv_get: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - grp = nt_group_getinfo(args->gname, RWLOCK_READER); - if (grp) { - priv_attr = nt_group_getpriv(grp, args->privid); - retval = priv_attr; - } else { - retval = NT_STATUS_NO_SUCH_GROUP; - *err = SMB_DR_OP_ERR; - } - nt_group_putinfo(grp); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &retval, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_priv_set(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL; - ntgrp_dr_arg_t *args; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - nt_group_t *grp; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_priv_set: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); + if ((name = smb_dr_decode_string(argp, arg_size)) == 0) { *err = SMB_DR_OP_ERR_DECODE; return (NULL); } - grp = nt_group_getinfo(args->gname, RWLOCK_WRITER); - if (grp) { - ntstatus = nt_group_setpriv(grp, - args->privid, args->priv_attr); - } else { - ntstatus = NT_STATUS_NO_SUCH_GROUP; - *err = SMB_DR_OP_ERR; + *strres = '\0'; + sid_type = SidTypeUnknown; + status = mlsvc_lookup_name(name, &sid, &sid_type); + xdr_free(xdr_string, (char *)&name); + if (status == NT_STATUS_SUCCESS) { + /* pack the SID and its type in a string */ + nt_sid_format2(sid, strsid); + (void) snprintf(strres, sizeof (strres), "%d-%s", + sid_type, strsid); + free(sid); } - nt_group_putinfo(grp); /* Encode the result and return */ - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, &ntstatus, - xdr_uint32_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_list(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL, *scope = NULL; - ntgrp_dr_arg_t *args; - ntgrp_list_t list; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_list: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - bzero(&list, sizeof (ntgrp_list_t)); - scope = args->scope; - if (scope == NULL) - scope = "*"; - nt_group_list(args->offset, scope, &list); - - /* Encode the result and return */ - if ((rbuf = smb_dr_encode_grp_list(SMB_DR_OP_SUCCESS, &list, + if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, strres, rbufsize)) == NULL) { *err = SMB_DR_OP_ERR_ENCODE; *rbufsize = 0; } - smb_group_free_list(&list, 1); - free(args); return (rbuf); } /*ARGSUSED*/ static char * -smb_dop_group_member_list(char *argp, size_t arg_size, +smb_dop_lookup_sid(char *argp, size_t arg_size, door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) { char *rbuf = NULL; - ntgrp_dr_arg_t *args; - nt_group_t *grp = NULL; - ntgrp_member_list_t members; + char *name = NULL; + uint32_t status; + nt_sid_t *sid; + char *strsid; *err = SMB_DR_OP_SUCCESS; *rbufsize = 0; /* Decode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_group_dr_listmember: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - if (smb_dr_decode_common(argp, arg_size, - xdr_ntgrp_dr_arg_t, args) != 0) { - free(args); + if ((strsid = smb_dr_decode_string(argp, arg_size)) == 0) { *err = SMB_DR_OP_ERR_DECODE; return (NULL); } - bzero(&members, sizeof (ntgrp_member_list_t)); - bzero(&members.members, SMB_GROUP_PER_LIST * sizeof (members_list)); - if ((!args->gname) || (strlen(args->gname) == 0)) { - free(args); - *err = SMB_DR_OP_ERR; - return (NULL); - } - grp = nt_group_getinfo(args->gname, RWLOCK_READER); - if (grp) { - (void) nt_group_member_list(args->offset, grp, &members); - } - nt_group_putinfo(grp); + sid = nt_sid_strtosid(strsid); + status = mlsvc_lookup_sid(sid, &name); + free(sid); + if (status != NT_STATUS_SUCCESS) + name = strsid; /* Encode the result and return */ - if ((rbuf = smb_dr_encode_grp_memberlist(SMB_DR_OP_SUCCESS, &members, + if ((rbuf = smb_dr_encode_string(SMB_DR_OP_SUCCESS, name, rbufsize)) == NULL) { *err = SMB_DR_OP_ERR_ENCODE; *rbufsize = 0; } - smb_group_free_memberlist(&members, 1); - free(args); - return (rbuf); -} - -/*ARGSUSED*/ -static char * -smb_dop_group_member_count(char *argp, size_t arg_size, - door_desc_t *dp, uint_t n_desc, size_t *rbufsize, int *err) -{ - char *rbuf = NULL, *gname = NULL; - ntgrp_dr_arg_t *enc_args; - nt_group_t *grp = NULL; - int num = 0; - uint32_t ntstatus = NT_STATUS_UNSUCCESSFUL; - - *err = SMB_DR_OP_SUCCESS; - *rbufsize = 0; - - /* Decode */ - if ((gname = smb_dr_decode_string(argp, arg_size)) == 0) { - *err = SMB_DR_OP_ERR_DECODE; - return (NULL); - } - - grp = nt_group_getinfo(gname, RWLOCK_READER); - if (grp) { - num = nt_group_num_members(grp); - ntstatus = NT_STATUS_SUCCESS; - } else { - ntstatus = NT_STATUS_NO_SUCH_GROUP; - } - nt_group_putinfo(grp); + if (status == NT_STATUS_SUCCESS) + free(name); - /* Encode the result and return */ - if ((enc_args = (ntgrp_dr_arg_t *) - malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, - "smb_dop_group_member_count: cannot allocate memory"); - *err = SMB_DR_OP_ERR; - return (NULL); - } - bzero(enc_args, sizeof (ntgrp_dr_arg_t)); - enc_args->count = num; - enc_args->ntstatus = ntstatus; - if ((rbuf = smb_dr_encode_common(SMB_DR_OP_SUCCESS, enc_args, - xdr_ntgrp_dr_arg_t, rbufsize)) == NULL) { - *err = SMB_DR_OP_ERR_ENCODE; - *rbufsize = 0; - } - free(enc_args); + xdr_free(xdr_string, (char *)&strsid); return (rbuf); } diff --git a/usr/src/cmd/smbsrv/smbd/smbd_door_server.c b/usr/src/cmd/smbsrv/smbd/smbd_door_server.c index ebdc051b79..e70b7f124f 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_door_server.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_door_server.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,6 @@ #include <errno.h> #include <syslog.h> #include <unistd.h> -#include <varargs.h> #include <stdio.h> #include <synch.h> #include <string.h> @@ -179,25 +178,17 @@ smb_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, switch (req_type) { case SMBD_DOOR_PARAM_GET: { smb_cfg_id_t id; - char *value = NULL; - char *empty = ""; + char value[MAX_VALUE_BUFLEN]; id = smb_dr_get_uint32(dec_ctx); dec_status = smb_dr_decode_finish(dec_ctx); - if (dec_status != 0) { + if (dec_status != 0) goto decode_error; - } - smb_config_rdlock(); - value = smb_config_getstr(id); + (void) smb_config_getstr(id, value, sizeof (value)); smb_dr_put_int32(enc_ctx, SMBD_DOOR_SRV_SUCCESS); - - if (value) - smb_dr_put_string(enc_ctx, value); - else - smb_dr_put_string(enc_ctx, empty); - smb_config_unlock(); + smb_dr_put_string(enc_ctx, value); break; } @@ -214,13 +205,10 @@ smb_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, goto decode_error; } - smb_config_wrlock(); - if (smb_config_set(id, value) == 0) { + if (smb_config_setstr(id, value) == SMBD_SMF_OK) smb_dr_put_int32(enc_ctx, SMBD_DOOR_SRV_SUCCESS); - } else { + else smb_dr_put_int32(enc_ctx, SMBD_DOOR_SRV_ERROR); - } - smb_config_unlock(); smb_dr_free_string(value); break; } @@ -262,20 +250,6 @@ smb_srv_door(void *cookie, char *ptr, size_t size, door_desc_t *dp, smb_dr_put_int32(enc_ctx, rc); break; - case SMBD_DOOR_ADS_DOMAIN_CHANGED: - domain = smb_dr_get_string(dec_ctx); - dec_status = smb_dr_decode_finish(dec_ctx); - if (dec_status != 0) { - smb_dr_free_string(domain); - goto decode_error; - } - - rc = ads_domain_change_notify_handler(domain); - smb_dr_put_int32(enc_ctx, SMBD_DOOR_SRV_SUCCESS); - smb_dr_put_int32(enc_ctx, rc); - smb_dr_free_string(domain); - break; - default: goto decode_error; } diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c index 90e4059abd..5e7d76396b 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_join.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -109,12 +109,20 @@ smbd_join(smb_joininfo_t *info) unsigned char passwd_hash[SMBAUTH_HASH_SZ]; char plain_passwd[PASS_LEN + 1]; char plain_user[PASS_LEN + 1]; + char nbt_domain[SMB_PI_MAX_DOMAIN]; + char fqdn[MAXHOSTNAMELEN]; if (info->mode == SMB_SECMODE_WORKGRP) { - smb_config_wrlock(); + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { + if (ads_domain_change_cleanup("") != 0) { + syslog(LOG_ERR, "smbd: unable to remove the" + " old keys from the Kerberos keytab. " + "Please remove the old keys for your " + "host principal."); + } + } (void) smb_config_set_secmode(info->mode); - (void) smb_config_set(SMB_CI_DOMAIN_NAME, info->domain_name); - smb_config_unlock(); + (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, info->domain_name); return (NT_STATUS_SUCCESS); } @@ -124,10 +132,25 @@ smbd_join(smb_joininfo_t *info) * will ensure that we don't attempt a NETLOGON_SAMLOGON * when attempting to find the PDC. */ - smb_set_domain_member(0); + (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_FALSE); + + (void) strlcpy(plain_user, info->domain_username, sizeof (plain_user)); + (void) strlcpy(plain_passwd, info->domain_passwd, + sizeof (plain_passwd)); + (void) smb_resolve_netbiosname(info->domain_name, nbt_domain, + sizeof (nbt_domain)); - (void) strcpy(plain_user, info->domain_username); - (void) strcpy(plain_passwd, info->domain_passwd); + if (smb_resolve_fqdn(info->domain_name, fqdn, sizeof (fqdn)) != 1) { + syslog(LOG_ERR, "smbd: fully-qualified domain name is unknown"); + return (NT_STATUS_INVALID_PARAMETER); + } + + if (ads_domain_change_cleanup(fqdn)) { + syslog(LOG_ERR, "smbd: unable to remove the old keys from the" + " Kerberos keytab. Please remove the old keys for your " + "host principal."); + return (NT_STATUS_INTERNAL_ERROR); + } if (smb_auth_ntlm_hash(plain_passwd, passwd_hash) != SMBAUTH_SUCCESS) { status = NT_STATUS_INTERNAL_ERROR; @@ -138,7 +161,7 @@ smbd_join(smb_joininfo_t *info) smbrdr_ipc_set(plain_user, passwd_hash); - if (locate_resource_pdc(info->domain_name)) { + if (locate_resource_pdc(nbt_domain)) { if ((pi = smb_getdomaininfo(0)) == 0) { status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; syslog(LOG_ERR, "smbd: could not get domain controller" @@ -155,11 +178,9 @@ smbd_join(smb_joininfo_t *info) plain_user, plain_passwd); if (status == NT_STATUS_SUCCESS) { - smb_config_wrlock(); (void) smb_config_set_secmode(SMB_SECMODE_DOMAIN); - (void) smb_config_set(SMB_CI_DOMAIN_NAME, + (void) smb_config_setstr(SMB_CI_DOMAIN_NAME, info->domain_name); - smb_config_unlock(); smbrdr_ipc_commit(); return (status); } @@ -296,8 +317,8 @@ smb_netlogon_dc_browser(void *arg) SMB_PI_MAX_DOMAIN); smb_setdomaininfo(NULL, NULL, 0); - if (msdcs_lookup_ads() == 0) { - if (smb_is_domain_member()) + if (msdcs_lookup_ads(resource_domain) == 0) { + if (smb_config_getbool(SMB_CI_DOMAIN_MEMB)) protocol = NETLOGON_PROTO_SAMLOGON; else protocol = NETLOGON_PROTO_NETLOGON; diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c index d174aeb18e..ca10cabb19 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_main.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -333,7 +333,6 @@ smbd_service_init(void) int door_id; int rc; - int ddns_enabled; uint32_t mode; char resource_domain[SMB_PI_MAX_DOMAIN]; int i; @@ -364,35 +363,28 @@ smbd_service_init(void) return (1); } - /* - * Need to load the configuration data prior to getting the - * interface information. - */ - if (smb_config_load() != 0) { - smbd_report("failed to load configuration data"); + (void) smb_nicmon_start(); + if (dns_msgid_init() != 0) { + smbd_report("DNS message id initialization failed"); return (1); } - smb_resolver_init(); - (void) smb_nicmon_start(); - smbrdr_init(); - smb_netbios_start(); + if (smb_netbios_start() != 0) + smbd_report("NetBIOS services failed to start"); + else + smbd_report("NetBIOS services started"); + if (smb_netlogon_init() != 0) { smbd_report("netlogon initialization failed"); return (1); } - smb_config_rdlock(); - resource_domain[0] = '\0'; - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); (void) utf8_strupr(resource_domain); - smb_config_unlock(); - - mode = smb_get_security_mode(); + mode = smb_config_get_secmode(); if (mode == SMB_SECMODE_DOMAIN) (void) locate_resource_pdc(resource_domain); @@ -403,21 +395,14 @@ smbd_service_init(void) } if ((rc = nt_domain_init(resource_domain, mode)) != 0) { - if (rc == SMB_DOMAIN_NOMACHINE_SID) - smbd_report("No Security Identifier (SID) has been " - "generated for this system.\n" - "Check idmap service configuration."); - - if (rc == SMB_DOMAIN_NODOMAIN_SID) { - /* Get the domain sid from domain controller */ - if ((rc = lsa_query_primary_domain_info()) != 0) - smbd_report("Failed to get the Security " - "Identifier (SID) of domain %s", - resource_domain); - } - return (rc); + if (rc == SMB_DOMAIN_NOMACHINE_SID) { + smbd_report( + "no machine SID: check idmap configuration"); + return (rc); + } } + ads_init(); if ((rc = mlsvc_init()) != 0) { smbd_report("msrpc initialization failed"); return (rc); @@ -436,12 +421,8 @@ smbd_service_init(void) return (rc); /* Call dyndns update - Just in case its configured to refresh DNS */ - smb_config_rdlock(); - ddns_enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); - smb_config_unlock(); - if (ddns_enabled) { + if (smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) (void) dyndns_update(); - } if ((rc = smbd_kernel_bind()) != 0) smbd_report("kernel bind error: %s", strerror(errno)); @@ -457,6 +438,7 @@ smbd_service_init(void) smbd_report("winpipe ioctl: %s", strerror(errno)); } + (void) smb_lgrp_start(); return (lmshare_start()); } @@ -484,8 +466,8 @@ smbd_service_fini(void) smb_lmshrd_srv_stop(); lmshare_stop(); smb_nicmon_stop(); - smb_resolver_close(); smb_idmap_stop(); + smb_lgrp_stop(); smbd_remove_ccache(); } @@ -551,7 +533,7 @@ smbd_refresh_monitor(void *arg) * We've been woken up by a refresh event so go do * what is necessary. */ - (void) smb_config_load(); + ads_refresh(); smb_nic_build_info(); (void) smb_netbios_name_reconfig(); (void) smb_browser_config(); @@ -705,7 +687,7 @@ smbd_setup_options(int argc, char *argv[]) if ((grp = getgrnam("sys")) != NULL) smbd.s_gid = grp->gr_gid; - smbd.s_fg = smb_get_fg_flag(); + smbd.s_fg = smb_config_get_fg_flag(); while ((c = getopt(argc, argv, ":f")) != -1) { switch (c) { diff --git a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c index 3ce7927215..986cef687c 100755 --- a/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_mlsvc_doorsvc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -209,8 +209,6 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, inpipe = context->inpipe; (void) strcpy(inpipe->sp_pipename, tmp_pipe.sp_pipename); - inpipe->sp_datalen = tmp_pipe.sp_datalen; - bcopy(bufp, inpipe->sp_data, inpipe->sp_datalen); outpipe = context->outpipe; (void) strcpy(outpipe->sp_pipename, "OUTPIPE"); @@ -227,7 +225,7 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, if (context == NULL) goto zero_exit; - context->inpipe->sp_datalen = context->inlen; + inpipe->sp_datalen = context->inlen; context->inlen = 0; context->outcookie = 0; @@ -235,6 +233,9 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, } if (mdhin.md_call_type == SMB_RPC_TRANSACT) { + bcopy(bufp, inpipe->sp_data, tmp_pipe.sp_datalen); + inpipe->sp_datalen = tmp_pipe.sp_datalen; + context = mlrpc_process(inpipe->sp_pipeid, user_ctx); if (context == NULL) goto zero_exit; @@ -246,13 +247,14 @@ smb_winpipe_request(void *cookie, char *argp, size_t arg_size, } if (mdhin.md_call_type == SMB_RPC_WRITE) { - bcopy(inpipe->sp_data, context->inpipe->sp_data + - context->inlen, inpipe->sp_datalen); /* - * if we get another RPC_WRITE then we need to append + * Append write data to the stream. */ - context->inlen += inpipe->sp_datalen; - context->inpipe->sp_datalen = context->inlen; + bcopy(bufp, inpipe->sp_data + context->inlen, + tmp_pipe.sp_datalen); + inpipe->sp_datalen += tmp_pipe.sp_datalen; + context->inlen += tmp_pipe.sp_datalen; + goto zero_exit; } diff --git a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c index e13f7c457d..148f4800d1 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -179,11 +179,9 @@ smb_setup_eventpipe(int *read_pipe, int *write_pipe) static void smb_process_nic_change() { - int ddns_enabled; + boolean_t ddns_enabled; - smb_config_rdlock(); - ddns_enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); - smb_config_unlock(); + ddns_enabled = smb_config_getbool(SMB_CI_DYNDNS_ENABLE); /* Clear rev zone before creating if list */ if (ddns_enabled) { diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 0aec8857f3..02d7c65ca7 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -553,7 +553,7 @@ libshare: libscf libzfs libuuid libfsmgt libsecdb libexacct/demo: libexacct libproject libsocket libnsl libtsalarm: libpcp smbsrv: libsocket libnsl libmd libxnet libpthread librt \ - libshare libidmap pkcs11 + libshare libidmap pkcs11 libsqlite libvscan: libscf # diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index 5716ef931c..74bb0af7e9 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -217,15 +217,6 @@ sa_errorstr(int err) case SA_PATH_IS_PARENTDIR: ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); break; - case SA_KRB_KEYTAB_ERR: - ret = dgettext(TEXT_DOMAIN, "unable to remove the old keys" - " from the Kerberos keytab. Please manually remove" - " the old keys for your host principal prior to setting" - " the ads_domain property"); - break; - case SA_NO_SERVICE: - ret = dgettext(TEXT_DOMAIN, "service is not running"); - break; default: (void) snprintf(errstr, sizeof (errstr), dgettext(TEXT_DOMAIN, "unknown %d"), err); diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h index af6e2db2f8..b45b747d9a 100644 --- a/usr/src/lib/libshare/common/libshare.h +++ b/usr/src/lib/libshare/common/libshare.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -85,8 +85,6 @@ typedef void *sa_handle_t; /* opaque handle to access core functions */ #define SA_MULTIPLE_ERROR 26 /* multiple protocols reported error */ #define SA_PATH_IS_SUBDIR 27 /* check_path found path is subdir */ #define SA_PATH_IS_PARENTDIR 28 /* check_path found path is parent */ -#define SA_KRB_KEYTAB_ERR 29 /* fail to delete old keytab entries */ -#define SA_NO_SERVICE 30 /* service isn't running */ /* API Initialization */ #define SA_INIT_SHARE_API 0x0001 /* init share specific interface */ diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c index 9aa98e9a37..0a3ed7535b 100644 --- a/usr/src/lib/libshare/smb/libshare_smb.c +++ b/usr/src/lib/libshare/smb/libshare_smb.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,18 +77,21 @@ static int string_length_check_validator(int, char *); static int true_false_validator(int, char *); static int ip_address_validator_empty_ok(int, char *); static int ip_address_csv_list_validator_empty_ok(int, char *); -static int ipc_mode_validator(int, char *); static int path_validator(int, char *); static int smb_enable_resource(sa_resource_t); static int smb_disable_resource(sa_resource_t); static uint64_t smb_share_features(void); static int smb_list_transient(sa_handle_t); -static int smb_domain_change_event(char *new_domain); + +extern void lmshrd_door_close(void); /* size of basic format allocation */ #define OPT_CHUNK 1024 +/* size of string for types - big enough to hold "dependency" */ +#define SCFTYPE_LEN 32 + /* * Indexes of entries in smb_proto_options table. * Changes to smb_proto_options table may require @@ -245,6 +248,50 @@ smb_isonline(void) } /* + * smb_isdisabled() + * + * Determine if the SMF service instance is in the disabled state or + * not. A number of operations depend on this state. + */ +static boolean_t +smb_isdisabled(void) +{ + char *str; + boolean_t ret = B_FALSE; + + if ((str = smf_get_state(SMBD_DEFAULT_INSTANCE_FMRI)) != NULL) { + ret = (strcmp(str, SCF_STATE_STRING_DISABLED) == 0); + free(str); + } + return (ret); +} + +/* + * smb_isautoenable() + * + * Determine if the SMF service instance auto_enabled set or not. A + * number of operations depend on this state. The property not being + * set or being set to true means autoenable. Only being set to false + * is not autoenabled. + */ +static boolean_t +smb_isautoenable(void) +{ + boolean_t ret = B_TRUE; + scf_simple_prop_t *prop; + uint8_t *retstr; + + prop = scf_simple_prop_get(NULL, SMBD_DEFAULT_INSTANCE_FMRI, + "application", "auto_enable"); + if (prop != NULL) { + retstr = scf_simple_prop_next_boolean(prop); + ret = *retstr != 0; + scf_simple_prop_free(prop); + } + return (ret); +} + +/* * smb_enable_share tells the implementation that it is to enable the share. * This entails converting the path and options into the appropriate ioctl * calls. It is assumed that all error checking of paths, etc. were @@ -273,7 +320,12 @@ smb_enable_share(sa_share_t share) if (path == NULL) return (SA_NO_SUCH_PATH); + /* + * If administratively disabled, don't try to start anything. + */ online = smb_isonline(); + if (!online && !smb_isautoenable() && smb_isdisabled()) + goto done; iszfs = sa_path_is_zfs(path); @@ -374,11 +426,28 @@ smb_enable_resource(sa_resource_t resource) sa_optionset_t opts; sa_share_t share; lmshare_info_t si; - int ret; + int ret = SA_OK; + int err; + boolean_t isonline; share = sa_get_resource_parent(resource); if (share == NULL) return (SA_NO_SUCH_PATH); + + /* + * If administratively disabled, don't try to start anything. + */ + isonline = smb_isonline(); + if (!isonline && !smb_isautoenable() && smb_isdisabled()) + goto done; + + if (!isonline) + ret = smb_enable_service(); + if (!smb_isonline()) { + ret = SA_OK; + goto done; + } + path = sa_get_share_attr(share, "path"); if (path == NULL) return (SA_SYSTEM_ERR); @@ -388,21 +457,25 @@ smb_enable_resource(sa_resource_t resource) return (SA_NO_SUCH_RESOURCE); } - ret = smb_enable_service(); - - if (!smb_isonline()) { - ret = SA_OK; - goto done; - } - opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1); smb_build_lmshare_info(rname, path, opts, &si); sa_free_attr_string(path); sa_free_attr_string(rname); sa_free_derived_optionset(opts); - if (lmshrd_add(&si) != NERR_Success) + + /* + * Attempt to add the share. Any error that occurs if it was + * online is an error but don't count NERR_DuplicateName if + * smb/server had to be brought online since bringing the + * service up will enable the share that was just added prior + * to the attempt to enable. + */ + + err = lmshrd_add(&si); + if (err == NERR_Success || !(!isonline && err == NERR_DuplicateName)) + (void) sa_update_sharetab(share, "smb"); + else return (SA_NOT_SHARED); - (void) sa_update_sharetab(share, "smb"); done: return (ret); @@ -670,85 +743,44 @@ smb_validate_property(sa_property_t property, sa_optionset_t parent) */ struct smb_proto_option_defs { - char *name; /* display name -- remove protocol identifier */ int smb_index; int32_t minval; int32_t maxval; /* In case of length of string this should be max */ int (*validator)(int, char *); int32_t refresh; } smb_proto_options[] = { - { SMB_CD_SYS_CMNT, - SMB_CI_SYS_CMNT, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_MAX_WORKERS, - SMB_CI_MAX_WORKERS, 64, 1024, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_NBSCOPE, - SMB_CI_NBSCOPE, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_RDR_IPCMODE, - SMB_CI_RDR_IPCMODE, 0, 0, ipc_mode_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_LM_LEVEL, - SMB_CI_LM_LEVEL, 2, 5, range_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_KEEPALIVE, - SMB_CI_KEEPALIVE, 20, 5400, range_check_validator_zero_ok, - SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_SRV1, - SMB_CI_WINS_SRV1, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_SRV2, - SMB_CI_WINS_SRV2, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_WINS_EXCL, - SMB_CI_WINS_EXCL, 0, MAX_VALUE_BUFLEN, - ip_address_csv_list_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_SIGNING_ENABLE, - SMB_CI_SIGNING_ENABLE, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_SIGNING_REQD, - SMB_CI_SIGNING_REQD, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_RESTRICT_ANON, - SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DOMAIN_SRV, - SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN, - ip_address_validator_empty_ok, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_ENABLE, - SMB_CI_ADS_ENABLE, 0, 0, true_false_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_USER, - SMB_CI_ADS_USER, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_USER_CONTAINER, - SMB_CI_ADS_USER_CONTAINER, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_DOMAIN, - SMB_CI_ADS_DOMAIN, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_PASSWD, - SMB_CI_ADS_PASSWD, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_IPLOOKUP, - SMB_CI_ADS_IPLOOKUP, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_ADS_SITE, - SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN, - string_length_check_validator, SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_ENABLE, - SMB_CI_DYNDNS_ENABLE, 0, 0, true_false_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_RETRY_SEC, - SMB_CI_DYNDNS_RETRY_SEC, 0, 20, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_DYNDNS_RETRY_COUNT, - SMB_CI_DYNDNS_RETRY_COUNT, 3, 5, range_check_validator, - SMB_REFRESH_REFRESH}, - { SMB_CD_AUTOHOME_MAP, - SMB_CI_AUTOHOME_MAP, 0, MAX_VALUE_BUFLEN, - path_validator}, - {NULL, -1, 0, 0, NULL} + { SMB_CI_SYS_CMNT, 0, MAX_VALUE_BUFLEN, + string_length_check_validator, SMB_REFRESH_REFRESH }, + { SMB_CI_MAX_WORKERS, 64, 1024, range_check_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_NBSCOPE, 0, MAX_VALUE_BUFLEN, + string_length_check_validator, 0 }, + { SMB_CI_LM_LEVEL, 2, 5, range_check_validator, 0 }, + { SMB_CI_KEEPALIVE, 20, 5400, range_check_validator_zero_ok, + SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_SRV1, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_SRV2, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_WINS_EXCL, 0, MAX_VALUE_BUFLEN, + ip_address_csv_list_validator_empty_ok, SMB_REFRESH_REFRESH }, + { SMB_CI_SIGNING_ENABLE, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_SIGNING_REQD, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_RESTRICT_ANON, 0, 0, true_false_validator, + SMB_REFRESH_REFRESH }, + { SMB_CI_DOMAIN_SRV, 0, MAX_VALUE_BUFLEN, + ip_address_validator_empty_ok, 0 }, + { SMB_CI_ADS_SITE, 0, MAX_VALUE_BUFLEN, + 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 }, }; +#define SMB_OPT_NUM \ + (sizeof (smb_proto_options) / sizeof (smb_proto_options[0])) + /* * Check the range of value as int range. */ @@ -884,22 +916,6 @@ ip_address_csv_list_validator_empty_ok(int index, char *value) } /* - * Check IPC mode - */ -/*ARGSUSED*/ -static int -ipc_mode_validator(int index, char *value) -{ - if (value == NULL) - return (SA_BAD_VALUE); - if (strcasecmp(value, "anon") == 0) - return (SA_OK); - if (strcasecmp(value, "auth") == 0) - return (SA_OK); - return (SA_BAD_VALUE); -} - -/* * Check path */ /*ARGSUSED*/ @@ -937,10 +953,14 @@ static int findprotoopt(char *name) { int i; - for (i = 0; smb_proto_options[i].name != NULL; i++) { - if (strcasecmp(smb_proto_options[i].name, name) == 0) + char *sc_name; + + for (i = 0; i < SMB_OPT_NUM; i++) { + sc_name = smb_config_getname(smb_proto_options[i].smb_index); + if (strcasecmp(sc_name, name) == 0) return (i); } + return (-1); } @@ -954,21 +974,22 @@ static int smb_load_proto_properties() { sa_property_t prop; + char value[MAX_VALUE_BUFLEN]; + char *name; int index; - char *value; + int rc; protoset = sa_create_protocol_properties(SMB_PROTOCOL_NAME); if (protoset == NULL) return (SA_NO_MEMORY); - if (smb_config_load() != 0) - return (SA_CONFIG_ERR); - for (index = 0; smb_proto_options[index].name != NULL; index++) { - value = smb_config_getenv(smb_proto_options[index].smb_index); - prop = sa_create_property( - smb_proto_options[index].name, value != NULL ? value : ""); - if (value != NULL) - free(value); + for (index = 0; index < SMB_OPT_NUM; index++) { + rc = smb_config_get(smb_proto_options[index].smb_index, + value, sizeof (value)); + if (rc != SMBD_SMF_OK) + continue; + name = smb_config_getname(smb_proto_options[index].smb_index); + prop = sa_create_property(name, value); if (prop != NULL) (void) sa_add_protocol_property(protoset, prop); } @@ -1004,6 +1025,8 @@ smb_share_fini(void) { xmlFreeNode(protoset); protoset = NULL; + + (void) lmshrd_door_close(); } /* @@ -1019,6 +1042,140 @@ smb_get_proto_set(void) } /* + * smb_enable_dependencies() + * + * SMBD_DEFAULT_INSTANCE_FMRI may have some dependencies that aren't + * enabled. This will attempt to enable all of them. + */ +static void +smb_enable_dependencies(const char *fmri) +{ + scf_handle_t *handle; + scf_service_t *service; + scf_instance_t *inst = NULL; + scf_iter_t *iter; + scf_property_t *prop; + scf_value_t *value; + scf_propertygroup_t *pg; + scf_scope_t *scope; + char type[SCFTYPE_LEN]; + char *dependency; + char *servname; + int maxlen; + + /* + * Get all required handles and storage. + */ + handle = scf_handle_create(SCF_VERSION); + if (handle == NULL) + return; + + if (scf_handle_bind(handle) != 0) { + scf_handle_destroy(handle); + return; + } + + maxlen = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); + if (maxlen == (ssize_t)-1) + maxlen = MAXPATHLEN; + + dependency = malloc(maxlen); + + service = scf_service_create(handle); + + iter = scf_iter_create(handle); + + pg = scf_pg_create(handle); + + prop = scf_property_create(handle); + + value = scf_value_create(handle); + + scope = scf_scope_create(handle); + + if (service == NULL || iter == NULL || pg == NULL || prop == NULL || + value == NULL || scope == NULL || dependency == NULL) + goto done; + + /* + * We passed in the FMRI for the default instance but for + * some things we need the simple form so construct it. Since + * we reuse the storage that dependency points to, we need to + * use the servname early. + */ + (void) snprintf(dependency, maxlen, "%s", fmri + sizeof ("svc:")); + servname = strrchr(dependency, ':'); + if (servname == NULL) + goto done; + *servname = '\0'; + servname = dependency; + + /* + * Setup to iterate over the service property groups, only + * looking at those that are "dependency" types. The "entity" + * property will have the FMRI of the service we are dependent + * on. + */ + if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) != 0) + goto done; + + if (scf_scope_get_service(scope, servname, service) != 0) + goto done; + + if (scf_iter_service_pgs(iter, service) != 0) + goto done; + + while (scf_iter_next_pg(iter, pg) > 0) { + char *services[2]; + /* + * Have a property group for the service. See if it is + * a dependency pg and only do operations on those. + */ + if (scf_pg_get_type(pg, type, SCFTYPE_LEN) <= 0) + continue; + + if (strncmp(type, SCF_GROUP_DEPENDENCY, SCFTYPE_LEN) != 0) + continue; + /* + * Have a dependency. Attempt to enable it. + */ + if (scf_pg_get_property(pg, SCF_PROPERTY_ENTITIES, prop) != 0) + continue; + + if (scf_property_get_value(prop, value) != 0) + continue; + + services[1] = NULL; + + if (scf_value_get_as_string(value, dependency, maxlen) > 0) { + services[0] = dependency; + _check_services(services); + } + } + +done: + if (dependency != NULL) + free(dependency); + if (value != NULL) + scf_value_destroy(value); + if (prop != NULL) + scf_property_destroy(prop); + if (pg != NULL) + scf_pg_destroy(pg); + if (iter != NULL) + scf_iter_destroy(iter); + if (scope != NULL) + scf_scope_destroy(scope); + if (inst != NULL) + scf_instance_destroy(inst); + if (service != NULL) + scf_service_destroy(service); + + (void) scf_handle_unbind(handle); + scf_handle_destroy(handle); +} + +/* * How long to wait for service to come online */ #define WAIT_FOR_SERVICE 15 @@ -1032,21 +1189,25 @@ smb_enable_service(void) { int i; int ret = SA_OK; + char *service[] = { SMBD_DEFAULT_INSTANCE_FMRI, NULL }; if (!smb_isonline()) { - if (smf_enable_instance(SMBD_DEFAULT_INSTANCE_FMRI, 0) != 0) { - (void) fprintf(stderr, - dgettext(TEXT_DOMAIN, - "%s failed to restart: %s\n"), - SMBD_DEFAULT_INSTANCE_FMRI, - scf_strerror(scf_error())); - return (SA_CONFIG_ERR); - } + /* + * Attempt to start the idmap, and other dependent + * services, first. If it fails, the SMB service will + * ultimately fail so we use that as the error. If we + * don't try to enable idmap, smb won't start the + * first time unless the admin has done it + * manually. The service could be administratively + * disabled so we won't always get started. + */ + smb_enable_dependencies(SMBD_DEFAULT_INSTANCE_FMRI); + _check_services(service); /* Wait for service to come online */ for (i = 0; i < WAIT_FOR_SERVICE; i++) { if (smb_isonline()) { - ret = SA_OK; + ret = SA_OK; break; } else { ret = SA_BUSY; @@ -1079,45 +1240,6 @@ smb_validate_proto_prop(int index, char *name, char *value) } /* - * smb_domain_change_event - * - * This function is called whenever ads_domain is changed via sharectl. - * It will make a door call to trigger the ADS domain change event. - */ -static int -smb_domain_change_event(char *new_domain) -{ - char *orig_domain; - int rc = SA_OK; - - orig_domain = smb_config_getenv(SMB_CI_ADS_DOMAIN); - if (orig_domain == NULL) - return (rc); - - if (strcasecmp(orig_domain, new_domain) == 0) { - free(orig_domain); - return (rc); - } - - if (!smb_isonline()) { - free(orig_domain); - return (SA_NO_SERVICE); - } - - /* - * Clear the ADS_HOST_INFO cache - * and remove old keys from the - * Kerberos keytab. - */ - if (smb_ads_domain_change_notify(orig_domain) != 0) - rc = SA_KRB_KEYTAB_ERR; - - free(orig_domain); - return (rc); -} - - -/* * smb_set_proto_prop(prop) * * check that prop is valid. @@ -1141,13 +1263,9 @@ smb_set_proto_prop(sa_property_t prop) ret = smb_validate_proto_prop(index, name, value); if (ret == SA_OK) { opt = &smb_proto_options[index]; - if ((opt->smb_index == SMB_CI_ADS_DOMAIN) && - (ret = smb_domain_change_event(value)) - != SA_OK) - goto cleanup; /* Save to SMF */ - smb_config_setenv(opt->smb_index, value); + (void) smb_config_set(opt->smb_index, value); /* * Specialized refresh mechanisms can * be flagged in the proto_options and @@ -1162,7 +1280,6 @@ smb_set_proto_prop(sa_property_t prop) } } -cleanup: if (name != NULL) sa_free_attr_string(name); if (value != NULL) diff --git a/usr/src/lib/libshare/smb/smb_share_doorclnt.c b/usr/src/lib/libshare/smb/smb_share_doorclnt.c index 0ebf61b7a9..1a06278568 100644 --- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c +++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,15 +37,20 @@ #include <errno.h> #include <string.h> #include <strings.h> +#include <unistd.h> +#include <thread.h> +#include <synch.h> #include <smbsrv/libsmb.h> - #include <smbsrv/lmshare.h> #include <smbsrv/lmerr.h> #include <smbsrv/lmshare_door.h> #include <smbsrv/cifs.h> -int lmshrd_fildes = -1; +static int lmshrd_fildes = -1; +static uint64_t lmshrd_door_ncall = 0; +static mutex_t lmshrd_mutex; +static cond_t lmshrd_cv; char *lmshrd_desc[] = { "", @@ -72,116 +77,150 @@ char *lmshrd_desc[] = { }; /* - * Returns 0 on success. Otherwise, -1. + * Open the lmshrd door. This is a private call for use by + * lmshrd_door_enter() and must be called with lmshrd_mutex held. + * + * Returns the door fd on success. Otherwise, -1. */ static int -lmshrd_door_open(int opcode) +lmshrd_door_open(void) +{ + if (lmshrd_fildes == -1) { + if ((lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) + lmshrd_fildes = -1; + else + lmshrd_door_ncall = 0; + } + + return (lmshrd_fildes); +} + +/* + * Close the lmshrd door. + */ +void +lmshrd_door_close(void) { - int rc = 0; + (void) mutex_lock(&lmshrd_mutex); - if (lmshrd_fildes == -1 && - (lmshrd_fildes = open(LMSHR_DOOR_NAME, O_RDONLY)) < 0) { - syslog(LOG_DEBUG, "%s: open %s failed %s", lmshrd_desc[opcode], - LMSHR_DOOR_NAME, strerror(errno)); - rc = -1; + if (lmshrd_fildes != -1) { + while (lmshrd_door_ncall > 0) + (void) cond_wait(&lmshrd_cv, &lmshrd_mutex); + + if (lmshrd_fildes != -1) { + (void) close(lmshrd_fildes); + lmshrd_fildes = -1; + } } - return (rc); + + (void) mutex_unlock(&lmshrd_mutex); } /* - * Return 0 upon success. Otherwise, -1. + * Entry handler for lmshrd door calls. */ -static int -lmshrd_door_check_srv_status(int opcode, smb_dr_ctx_t *dec_ctx) +static door_arg_t * +lmshrd_door_enter(void) { - int status = smb_dr_get_int32(dec_ctx); - int err; - int rc = -1; + door_arg_t *arg; + char *buf; - switch (status) { - case LMSHR_DOOR_SRV_SUCCESS: - rc = 0; - break; + (void) mutex_lock(&lmshrd_mutex); - case LMSHR_DOOR_SRV_ERROR: - err = smb_dr_get_uint32(dec_ctx); - syslog(LOG_ERR, "%s: Encountered door server error %s", - lmshrd_desc[opcode], strerror(err)); - break; + if (lmshrd_door_open() == -1) { + (void) mutex_unlock(&lmshrd_mutex); + return (NULL); + } + + if ((arg = malloc(sizeof (door_arg_t) + LMSHR_DOOR_SIZE)) != NULL) { + buf = ((char *)arg) + sizeof (door_arg_t); + bzero(arg, sizeof (door_arg_t)); + arg->data_ptr = buf; + arg->rbuf = buf; + arg->rsize = LMSHR_DOOR_SIZE; - default: - syslog(LOG_ERR, "%s: Unknown door server status", - lmshrd_desc[opcode]); + ++lmshrd_door_ncall; } - if (rc != 0) { - if ((err = smb_dr_decode_finish(dec_ctx)) != 0) - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(err)); + (void) mutex_unlock(&lmshrd_mutex); + return (arg); +} + +/* + * Exit handler for lmshrd door calls. + */ +static void +lmshrd_door_exit(door_arg_t *arg, char *errmsg) +{ + if (errmsg) + syslog(LOG_DEBUG, "lmshrd_door: %s", errmsg); + + (void) mutex_lock(&lmshrd_mutex); + free(arg); + --lmshrd_door_ncall; + (void) cond_signal(&lmshrd_cv); + (void) mutex_unlock(&lmshrd_mutex); +} + +/* + * Return 0 upon success. Otherwise, -1. + */ +static int +lmshrd_door_check_status(smb_dr_ctx_t *dec_ctx) +{ + int status = smb_dr_get_int32(dec_ctx); + + if (status != LMSHR_DOOR_SRV_SUCCESS) { + if (status == LMSHR_DOOR_SRV_ERROR) + (void) smb_dr_get_uint32(dec_ctx); + return (-1); } - return (rc); + return (0); } uint64_t lmshrd_open_iterator(int mode) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; uint64_t lmshr_iter = 0; - int opcode = LMSHR_DOOR_OPEN_ITERATOR; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (lmshr_iter); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (lmshr_iter); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_OPEN_ITERATOR); smb_dr_put_int32(enc_ctx, mode); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (lmshr_iter); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (lmshr_iter); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (lmshr_iter); } lmshr_iter = smb_dr_get_lmshr_iterator(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (lmshr_iter); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (lmshr_iter); } @@ -189,312 +228,221 @@ lmshrd_open_iterator(int mode) DWORD lmshrd_close_iterator(uint64_t iterator) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_CLOSE_ITERATOR; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); + int rc; - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_CLOSE_ITERATOR); smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (NERR_Success); } DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; - int opcode = LMSHR_DOOR_ITERATE; + int rc; - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); bzero(si, sizeof (lmshare_info_t)); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ITERATE); smb_dr_put_lmshr_iterator(enc_ctx, iterator); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (NERR_Success); } DWORD lmshrd_list(int offset, lmshare_list_t *list) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_LIST; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_LIST); smb_dr_put_int32(enc_ctx, offset); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshr_list(dec_ctx, list); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); - + lmshrd_door_exit(arg, NULL); return (rc); } int lmshrd_num_shares(void) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - unsigned int status = 0; DWORD num_shares; - int opcode = LMSHR_DOOR_NUM_SHARES; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (-1); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (-1); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_NUM_SHARES); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (-1); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (-1); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (-1); } num_shares = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (-1); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (num_shares); } DWORD lmshrd_delete(char *share_name) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_DELETE; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_DELETE); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } @@ -502,316 +450,223 @@ lmshrd_delete(char *share_name) DWORD lmshrd_rename(char *from, char *to) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_RENAME; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_RENAME); smb_dr_put_string(enc_ctx, from); smb_dr_put_string(enc_ctx, to); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_getinfo(char *share_name, lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_GETINFO; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_GETINFO); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_add(lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_ADD; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_ADD); smb_dr_put_lmshare(enc_ctx, si); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); smb_dr_get_lmshare(dec_ctx, si); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } DWORD lmshrd_setinfo(lmshare_info_t *si) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status; DWORD rc; - int opcode = LMSHR_DOOR_SETINFO; - - if (lmshrd_door_open(opcode) == -1) - return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); - smb_dr_put_uint32(enc_ctx, opcode); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); + smb_dr_put_uint32(enc_ctx, LMSHR_DOOR_SETINFO); smb_dr_put_lmshare(enc_ctx, si); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_uint32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } static int lmshrd_check(char *share_name, int opcode) { - door_arg_t arg; - char *buf; - unsigned int used; + door_arg_t *arg; smb_dr_ctx_t *dec_ctx; smb_dr_ctx_t *enc_ctx; - int status, rc; + int rc; - if (lmshrd_door_open(opcode) == -1) + if ((arg = lmshrd_door_enter()) == NULL) return (NERR_InternalError); - buf = malloc(LMSHR_DOOR_SIZE); - if (!buf) - return (NERR_InternalError); - - enc_ctx = smb_dr_encode_start(buf, LMSHR_DOOR_SIZE); + enc_ctx = smb_dr_encode_start(arg->data_ptr, LMSHR_DOOR_SIZE); smb_dr_put_uint32(enc_ctx, opcode); smb_dr_put_string(enc_ctx, share_name); - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + rc = smb_dr_encode_finish(enc_ctx, (unsigned int *)&arg->data_size); + if (rc != 0) { + lmshrd_door_exit(arg, "encode error"); return (NERR_InternalError); } - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = LMSHR_DOOR_SIZE; - - if (door_call(lmshrd_fildes, &arg) < 0) { - syslog(LOG_DEBUG, "%s: Door call failed %s", - lmshrd_desc[opcode], strerror(errno)); - (void) free(buf); - lmshrd_fildes = -1; + if (door_call(lmshrd_fildes, arg) < 0) { + lmshrd_door_exit(arg, "door call error"); + lmshrd_door_close(); return (NERR_InternalError); } - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (lmshrd_door_check_srv_status(opcode, dec_ctx) != 0) { - (void) free(buf); + dec_ctx = smb_dr_decode_start(arg->data_ptr, arg->data_size); + if (lmshrd_door_check_status(dec_ctx) != 0) { + (void) smb_dr_decode_finish(dec_ctx); + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } rc = smb_dr_get_int32(dec_ctx); - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - lmshrd_desc[opcode], strerror(status)); - (void) free(buf); + if (smb_dr_decode_finish(dec_ctx) != 0) { + lmshrd_door_exit(arg, "decode error"); return (NERR_InternalError); } - (void) free(buf); + lmshrd_door_exit(arg, NULL); return (rc); } @@ -850,102 +705,3 @@ lmshrd_is_dir(char *path) { return (lmshrd_check(path, LMSHR_DOOR_IS_DIR)); } - -static char * -lmshare_decode_type(unsigned int stype) -{ - switch (stype) { - case STYPE_DISKTREE: - return ("Disk"); - case STYPE_PRINTQ: - return ("Print Queue"); - case STYPE_DEVICE: - return ("Device"); - case STYPE_IPC: - return ("IPC"); - case STYPE_DFS: - return ("DFS"); - case STYPE_SPECIAL: - return ("Special"); - default: - return ("Unknown"); - }; -} - - -static void -lmshare_loginfo(FILE *fp, lmshare_info_t *si) -{ - if (!si) { - return; - } - - (void) fprintf(fp, "\n%s Information:\n", si->share_name); - (void) fprintf(fp, "\tFolder: %s\n", si->directory); - (void) fprintf(fp, "\tType: %s\n", lmshare_decode_type(si->stype)); - (void) fprintf(fp, "\tComment: %s\n", si->comment); - - (void) fprintf(fp, "\tStatus: %s\n", - ((si->mode & LMSHRM_TRANS) ? "Transient" : "Permanent")); - - (void) fprintf(fp, "\tContainer: %s\n", si->container); -} - -int -lmshrd_dump_hash(char *logfname) -{ - lmshare_info_t si; - uint64_t it; - FILE *fp; - - if ((logfname == 0) || (*logfname == 0)) - fp = stdout; - else { - fp = fopen(logfname, "w"); - if (fp == 0) { - syslog(LOG_WARNING, "LmshareDump [%s]:" - " cannot create logfile", logfname); - syslog(LOG_WARNING, "LmshareDump:" - " output will be written on screen"); - } - } - - it = lmshrd_open_iterator(LMSHRM_PERM); - if (it == NULL) { - syslog(LOG_ERR, "LmshareDump: resource shortage"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - - if (lmshrd_iterate(it, &si) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator iterate failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - while (*si.share_name != 0) { - lmshare_loginfo(fp, &si); - if (lmshrd_iterate(it, &si) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator iterate failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - } - - if (lmshrd_close_iterator(it) != NERR_Success) { - syslog(LOG_ERR, "LmshareDump: Iterator close failed"); - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (1); - } - if (fp && fp != stdout) { - (void) fclose(fp); - } - return (0); -} diff --git a/usr/src/lib/libsqlite/Makefile.com b/usr/src/lib/libsqlite/Makefile.com index 49b42f553b..5bf5ebd84c 100644 --- a/usr/src/lib/libsqlite/Makefile.com +++ b/usr/src/lib/libsqlite/Makefile.com @@ -1,5 +1,5 @@ # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -48,7 +48,8 @@ include $(SRC)/lib/Makefile.lib SRCDIR = ../src TOOLDIR = ../tool -LIBS = $(RELOC) $(LINTLIB) +$(DYNLIB) := LDLIBS += -lc +LIBS = $(RELOC) $(LINTLIB) $(DYNLIB) $(LINTLIB) := SRCS = $(LINTSRC) @@ -88,7 +89,7 @@ SRCS = \ MYCPPFLAGS = -D_REENTRANT -DTHREADSAFE=1 -DHAVE_USLEEP=1 -I. -I.. -I$(SRCDIR) CPPFLAGS += $(MYCPPFLAGS) -MAPFILE = ../mapfile-sqlite +MAPFILES = ../mapfile-sqlite # Header files used by all library source files. # @@ -198,11 +199,11 @@ $(OBJS) $(OBJS:%.o=%-native.o): $(HDR) native: $(NATIVERELOC) $(RELOC): objs .WAIT $(OBJS) - $(LD) -r $(MAPFILE:%=-M%) -o $(RELOC) $(OBJS) + $(LD) -r $(MAPFILES:%=-M%) -o $(RELOC) $(OBJS) $(CTFMERGE) -t -f -L VERSION -o $(RELOC) $(OBJS) $(NATIVERELOC): objs .WAIT $(OBJS:%.o=%-native.o) - $(LD) -r $(MAPFILE:%=-M%) -o $(NATIVERELOC) $(OBJS:%.o=%-native.o) + $(LD) -r $(MAPFILES:%=-M%) -o $(NATIVERELOC) $(OBJS:%.o=%-native.o) opcodes.h: $(SRCDIR)/vdbe.c @echo "Generating $@"; \ diff --git a/usr/src/lib/libsqlite/i386/Makefile b/usr/src/lib/libsqlite/i386/Makefile index 1cdf2c61ae..743fead699 100644 --- a/usr/src/lib/libsqlite/i386/Makefile +++ b/usr/src/lib/libsqlite/i386/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,6 @@ include ../Makefile.com -install: $(ROOTLIBDIR)/$(RELOC) +install: $(ROOTLIBDIR)/$(RELOC) $(ROOTLIBS) $(ROOTLINKS) $(ROOTLIBDIR)/$(RELOC): all diff --git a/usr/src/lib/libsqlite/sparc/Makefile b/usr/src/lib/libsqlite/sparc/Makefile index 1cdf2c61ae..743fead699 100644 --- a/usr/src/lib/libsqlite/sparc/Makefile +++ b/usr/src/lib/libsqlite/sparc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,6 @@ include ../Makefile.com -install: $(ROOTLIBDIR)/$(RELOC) +install: $(ROOTLIBDIR)/$(RELOC) $(ROOTLIBS) $(ROOTLINKS) $(ROOTLIBDIR)/$(RELOC): all diff --git a/usr/src/lib/smbsrv/libmlrpc/Makefile.com b/usr/src/lib/smbsrv/libmlrpc/Makefile.com index cc5ba2923f..d4776174cd 100644 --- a/usr/src/lib/smbsrv/libmlrpc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlrpc/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,13 +29,13 @@ LIBRARY = libmlrpc.a VERS = .1 OBJS_COMMON = \ - mlndo.o \ - mlndr.o \ - mlrpc_client.o \ - mlrpc_encdec.o \ - mlrpc_heap.o \ - mlrpc_server.o \ - mlrpc_svc.o + ndr_client.o \ + ndr_heap.o \ + ndr_marshal.o \ + ndr_ops.o \ + ndr_process.o \ + ndr_server.o \ + ndr_svc.o NDLLIST = rpcpdu diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers index 2f8fea95f3..5166d7d3d9 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlrpc/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -48,6 +48,9 @@ SUNWprivate { mlrpc_process; mlrpc_register_service; mlrpc_release; + ndr_hdalloc; + ndr_hdfree; + ndr_hdlookup; ndr_mbstowcs; ndr_mbtowc; ndt__char; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c index 0f58231251..0f58231251 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_client.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_client.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_heap.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c index 97a16ea010..97a16ea010 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_heap.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_heap.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_encdec.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c index 884683dfe4..884683dfe4 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_encdec.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndo.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c index c469223c4d..c469223c4d 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlndo.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_ops.c diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c index e81225ede8..b64ada2955 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlndr.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_process.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1321,9 +1321,9 @@ mlndr_outer_string(struct ndr_reference *outer_ref) myref.inner_flags = NDR_F_NONE; /* - * Set up strlen_is so that we know what to - * expect later (see mlndr_s_wchar). + * Set up size_is and strlen_is for mlndr_s_wchar. */ + myref.size_is = size_is; myref.strlen_is = length_is; } @@ -1933,6 +1933,9 @@ mlndr_s_wchar(struct ndr_reference *encl_ref) if (count < 0) { return (0); } else if (count == 0) { + if (encl_ref->strlen_is != encl_ref->size_is) + break; + /* * If the input char is 0, mbtowc * returns 0 without setting wide_char. diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c index 2f442937be..a1f203c09c 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_server.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_server.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,8 +70,8 @@ static void mlrpc_reply_fault(struct mlrpc_xaction *, unsigned long); static int mlrpc_build_reply(struct mlrpc_xaction *); /* - * The is the RPC service server-side entry point. All MSRPC encoded - * messages should be passed through here. We use the same context + * This is the RPC service server-side entry point. All MSRPC encoded + * messages should be passed through here. We use the same context * structure as the client side but we don't need to set up the client * side info. */ @@ -98,6 +98,7 @@ mlrpc_process(int fid, smb_dr_user_ctx_t *user_ctx) return (NULL); bzero(mxa, sizeof (struct mlrpc_xaction)); + mxa->fid = fid; mxa->context = context; mxa->binding_list = context->binding; @@ -177,6 +178,8 @@ mlrpc_lookup(int fid) return (NULL); } + bzero(available->inpipe, sizeof (smb_pipe_t)); + bzero(available->outpipe, sizeof (smb_pipe_t)); available->fid = fid; available->inpipe->sp_pipeid = fid; available->outpipe->sp_pipeid = fid; @@ -205,6 +208,7 @@ mlrpc_release(int fid) context = &context_table[i]; if (context->fid == fid) { + ndr_hdclose(fid); free(context->inpipe); free(context->outpipe); bzero(context, sizeof (struct mlsvc_rpc_context)); @@ -267,8 +271,8 @@ mlrpc_s_bind(struct mlrpc_xaction *mxa) mlrpc_p_result_t *result; unsigned p_cont_id; struct mlrpc_binding *mbind; - mlrpc_uuid_t *as_uuid; - mlrpc_uuid_t *ts_uuid; + ndr_uuid_t *as_uuid; + ndr_uuid_t *ts_uuid; char as_buf[64]; char ts_buf[64]; int as_vers; @@ -414,8 +418,8 @@ mlrpc_s_alter_context(struct mlrpc_xaction *mxa) struct mlrpc_binding *mbind; struct mlrpc_service *msvc; unsigned p_cont_id; - mlrpc_uuid_t *as_uuid; - mlrpc_uuid_t *ts_uuid; + ndr_uuid_t *as_uuid; + ndr_uuid_t *ts_uuid; int as_vers; int ts_vers; mlrpc_port_any_t *sec_addr; diff --git a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_svc.c b/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c index 771e54b7e4..1c051b560e 100644 --- a/usr/src/lib/smbsrv/libmlrpc/common/mlrpc_svc.c +++ b/usr/src/lib/smbsrv/libmlrpc/common/ndr_svc.c @@ -19,26 +19,44 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" +#include <synch.h> #include <stdio.h> +#include <unistd.h> #include <string.h> #include <strings.h> +#include <assert.h> #include <smbsrv/libsmb.h> #include <smbsrv/ndr.h> #include <smbsrv/mlrpc.h> +#include <smbsrv/ntsid.h> + +/* + * Global list of allocated handles. Handles are used in various + * server-side RPC functions: typically, issued when a service is + * opened and obsoleted when it is closed. Clients should treat + * handles as opaque data. + */ +static ndr_handle_t *ndr_handle_list; +static mutex_t ndr_handle_lock; + +/* + * Table of registered services. + */ #define NDL_MAX_SERVICES 32 -static struct mlrpc_service *mlrpc_services[NDL_MAX_SERVICES]; +static mlrpc_service_t *mlrpc_services[NDL_MAX_SERVICES]; + struct mlrpc_stub_table * -mlrpc_find_stub_in_svc(struct mlrpc_service *msvc, int opnum) +mlrpc_find_stub_in_svc(mlrpc_service_t *msvc, int opnum) { struct mlrpc_stub_table *ste; @@ -50,10 +68,10 @@ mlrpc_find_stub_in_svc(struct mlrpc_service *msvc, int opnum) return (NULL); } -struct mlrpc_service * +mlrpc_service_t * mlrpc_find_service_by_name(const char *name) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; int i; for (i = 0; i < NDL_MAX_SERVICES; i++) { @@ -70,11 +88,11 @@ mlrpc_find_service_by_name(const char *name) return (NULL); } -struct mlrpc_service * -mlrpc_find_service_by_uuids(mlrpc_uuid_t *as_uuid, int as_vers, - mlrpc_uuid_t *ts_uuid, int ts_vers) +mlrpc_service_t * +mlrpc_find_service_by_uuids(ndr_uuid_t *as_uuid, int as_vers, + ndr_uuid_t *ts_uuid, int ts_vers) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; char abstract_syntax[128]; char transfer_syntax[128]; int i; @@ -130,9 +148,9 @@ mlrpc_find_service_by_uuids(mlrpc_uuid_t *as_uuid, int as_vers, * -3 Table overflow */ int -mlrpc_register_service(struct mlrpc_service *msvc) +mlrpc_register_service(mlrpc_service_t *msvc) { - struct mlrpc_service *p; + mlrpc_service_t *p; int free_slot = -1; int i; @@ -158,7 +176,7 @@ mlrpc_register_service(struct mlrpc_service *msvc) } void -mlrpc_unregister_service(struct mlrpc_service *msvc) +mlrpc_unregister_service(mlrpc_service_t *msvc) { int i; @@ -171,7 +189,7 @@ mlrpc_unregister_service(struct mlrpc_service *msvc) int mlrpc_list_services(char *buffer, int bufsize) { - struct mlrpc_service *msvc; + mlrpc_service_t *msvc; smb_ctxbuf_t ctx; int i; @@ -187,8 +205,144 @@ mlrpc_list_services(char *buffer, int bufsize) return (smb_ctxbuf_len(&ctx)); } +/* + * Allocate a handle for use with the server-side RPC functions. + * The handle contains the machine SID and an incrementing counter, + * which should make each handle unique. + * + * An arbitrary caller context can be associated with the handle + * via data; it will not be dereferenced by the handle API. + * + * The uuid for the new handle is returned after it has been added + * to the global handle list. + */ +ndr_hdid_t * +ndr_hdalloc(const ndr_xa_t *xa, const void *data) +{ + static ndr_hdid_t uuid; + ndr_handle_t *hd; + nt_sid_t *sid; + + if ((hd = malloc(sizeof (ndr_handle_t))) == NULL) + return (NULL); + + if (uuid.data[1] == 0) { + if ((sid = nt_domain_local_sid()) == NULL) + return (NULL); + + uuid.data[0] = 0; + uuid.data[1] = 0; + uuid.data[2] = sid->SubAuthority[1]; + uuid.data[3] = sid->SubAuthority[2]; + uuid.data[4] = sid->SubAuthority[3]; + } + + ++uuid.data[1]; + + bcopy(&uuid, &hd->nh_id, sizeof (ndr_hdid_t)); + hd->nh_fid = xa->fid; + hd->nh_svc = xa->binding->service; + hd->nh_data = (void *)data; + + (void) mutex_lock(&ndr_handle_lock); + hd->nh_next = ndr_handle_list; + ndr_handle_list = hd; + (void) mutex_unlock(&ndr_handle_lock); + + return (&hd->nh_id); +} + +/* + * Remove a handle from the global list and free it. + */ +void +ndr_hdfree(const ndr_xa_t *xa, const ndr_hdid_t *id) +{ + mlrpc_service_t *svc = xa->binding->service; + ndr_handle_t *hd; + ndr_handle_t **pphd; + + assert(id); + + (void) mutex_lock(&ndr_handle_lock); + pphd = &ndr_handle_list; + + while (*pphd) { + hd = *pphd; + + if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { + if (hd->nh_svc == svc) { + *pphd = hd->nh_next; + free(hd); + } + break; + } + + pphd = &(*pphd)->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); +} + +/* + * Lookup a handle by id. If the handle is in the list and it matches + * the specified service, a pointer to it is returned. Otherwise a null + * pointer is returned. + */ +ndr_handle_t * +ndr_hdlookup(const ndr_xa_t *xa, const ndr_hdid_t *id) +{ + mlrpc_service_t *svc = xa->binding->service; + ndr_handle_t *hd; + + assert(id); + (void) mutex_lock(&ndr_handle_lock); + hd = ndr_handle_list; + + while (hd) { + if (bcmp(&hd->nh_id, id, sizeof (ndr_hdid_t)) == 0) { + if (hd->nh_svc != svc) + break; + (void) mutex_unlock(&ndr_handle_lock); + return (hd); + } + + hd = hd->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); + return (NULL); +} + +/* + * Called when a pipe is closed to release any associated handles. + */ +void +ndr_hdclose(int fid) +{ + ndr_handle_t *hd; + ndr_handle_t **pphd; + + (void) mutex_lock(&ndr_handle_lock); + pphd = &ndr_handle_list; + + while (*pphd) { + hd = *pphd; + + if (hd->nh_fid == fid) { + *pphd = hd->nh_next; + free(hd); + continue; + } + + pphd = &(*pphd)->nh_next; + } + + (void) mutex_unlock(&ndr_handle_lock); +} + void -mlrpc_uuid_to_str(mlrpc_uuid_t *uuid, char *str) +mlrpc_uuid_to_str(ndr_uuid_t *uuid, char *str) { (void) sprintf(str, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x", uuid->data1, uuid->data2, uuid->data3, @@ -199,7 +353,7 @@ mlrpc_uuid_to_str(mlrpc_uuid_t *uuid, char *str) } int -mlrpc_str_to_uuid(char *str, mlrpc_uuid_t *uuid) +mlrpc_str_to_uuid(char *str, ndr_uuid_t *uuid) { char *p = str; char *q; diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com index 60f0c4f66d..0b32262027 100644 --- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com +++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #pragma ident "%Z%%M% %I% %E% SMI" @@ -34,7 +34,6 @@ OBJS_COMMON = \ lsar_open.o \ mlsvc_client.o \ mlsvc_dssetup.o \ - mlsvc_handle.o \ mlsvc_init.o \ mlsvc_logr.o \ mlsvc_lsa.o \ diff --git a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h index 71cc37af48..b77dde5340 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h +++ b/usr/src/lib/smbsrv/libmlsvc/common/libmlsvc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,8 @@ extern "C" { #endif extern int mlsvc_init(void); -extern int mlsvc_is_local_domain(const char *); +extern uint32_t mlsvc_lookup_name(char *, nt_sid_t **, uint16_t *); +extern uint32_t mlsvc_lookup_sid(nt_sid_t *, char **); extern DWORD lsa_query_primary_domain_info(void); extern DWORD lsa_query_account_domain_info(void); extern DWORD lsa_enum_trusted_domains(void); @@ -68,168 +69,6 @@ extern void smb_autohome_endent(void); extern smb_autohome_t *smb_autohome_getent(const char *name); extern smb_autohome_t *smb_autohome_lookup(const char *name); -/* - * Local groups - */ -#define NT_GROUP_FMRI_PREFIX "network/smb/group" - -typedef enum { - RWLOCK_NONE, - RWLOCK_WRITER, - RWLOCK_READER -} krwmode_t; - -typedef struct nt_group_data { - void *data; - int size; -} nt_group_data_t; - -/* - * IMPORTANT NOTE: - * If you change nt_group_member_t, nt_group_members_t, or nt_group_t - * structures, you MIGHT have to change following functions accordingly: - * nt_group_setfields - * nt_group_init_size - * nt_group_init - */ -typedef struct nt_group_member { - uint16_t info_size; /* size of the whole structure */ - uint16_t sid_name_use; /* type of the specified SID */ - char *account; /* Pointer to account name of member */ - nt_sid_t sid; /* Variable length */ -} nt_group_member_t; - -typedef struct nt_group_members { - uint32_t size; /* in bytes */ - uint32_t count; - nt_group_member_t list[ANY_SIZE_ARRAY]; -} nt_group_members_t; - -typedef struct nt_group { - time_t age; - nt_group_data_t info; - /* - * following fields point to a contigous block - * of memory that is read and written from/to DB - */ - uint32_t *attr; - uint16_t *sid_name_use; - char *name; - char *comment; - nt_sid_t *sid; - smb_privset_t *privileges; - nt_group_members_t *members; -} nt_group_t; - -typedef struct nt_group_iterator { - HT_ITERATOR *iterator; - int iteration; -} nt_group_iterator_t; - -extern int nt_group_num_groups(void); -extern uint32_t nt_group_add(char *, char *); -extern uint32_t nt_group_modify(char *, char *, char *); -extern uint32_t nt_group_delete(char *); -extern nt_group_t *nt_group_getinfo(char *, krwmode_t); -extern void nt_group_putinfo(nt_group_t *); - -extern int nt_group_getpriv(nt_group_t *, uint32_t); -extern uint32_t nt_group_setpriv(nt_group_t *, uint32_t, uint32_t); - -/* Member manipulation functions */ -extern int nt_group_is_member(nt_group_t *, nt_sid_t *); -extern uint32_t nt_group_del_member(nt_group_t *, void *, int); -extern uint32_t nt_group_add_member(nt_group_t *, nt_sid_t *, uint16_t, char *); -extern int nt_group_num_members(nt_group_t *); - -extern void nt_group_ht_lock(krwmode_t); -extern void nt_group_ht_unlock(void); - -extern nt_group_iterator_t *nt_group_open_iterator(void); -extern void nt_group_close_iterator(nt_group_iterator_t *); -extern nt_group_t *nt_group_iterate(nt_group_iterator_t *); - -extern int nt_group_cache_size(void); - -extern int nt_group_member_list(int offset, nt_group_t *grp, - ntgrp_member_list_t *rmembers); -extern void nt_group_list(int offset, char *pattern, ntgrp_list_t *list); - -extern uint32_t sam_init(void); - -extern uint32_t nt_group_add_member_byname(char *, char *); -extern uint32_t nt_group_del_member_byname(nt_group_t *, char *); -extern void nt_group_add_groupprivs(nt_group_t *, smb_privset_t *); - -extern uint32_t nt_groups_member_privs(nt_sid_t *, smb_privset_t *); -extern int nt_groups_member_ngroups(nt_sid_t *); -extern uint32_t nt_groups_member_groups(nt_sid_t *, smb_id_t *, int); -extern nt_group_t *nt_groups_lookup_rid(uint32_t); -extern int nt_groups_count(int); - -/* - * source for account name size is MSDN - */ -#define NT_GROUP_NAME_CHAR_MAX 32 -#define NT_GROUP_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_USER_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_MEMBER_NAME_MAX (NT_GROUP_NAME_CHAR_MAX * 3 + 1) -#define NT_GROUP_COMMENT_MAX 256 - -/* - * flags for count operation - */ -#define NT_GROUP_CNT_BUILTIN 1 -#define NT_GROUP_CNT_LOCAL 2 -#define NT_GROUP_CNT_ALL 3 - -/* - * flag to distinguish between add and modify - * operations. - */ -#define NT_GROUP_OP_CHANGE 1 -#define NT_GROUP_OP_SYNC 2 - -/* - * specify key type for deleting a member i.e. - * whether it's member's name or member's SID. - */ -#define NT_GROUP_KEY_SID 1 -#define NT_GROUP_KEY_NAME 2 - -/* Macro for walking members */ -#define NEXT_MEMBER(m) (nt_group_member_t *)((char *)(m) + (m)->info_size) - -/* - * When NT requests the security descriptor for a local file that - * doesn't already have a one, we generate one on-the-fly. The SD - * contains both user and group SIDs. The problem is that we need a - * way to distinguish a user SID from a group SID when NT performs a - * subsequent SID lookup to obtain the appropriate name to display. - * The following macros are used to map to and from an external - * representation so that we can tell the difference between UIDs - * and GIDs. The local UID/GID is shifted left and the LSB is used - * to distinguish the id type before it is inserted into the SID. - * We can then use this type identifier during lookup operations. - */ -#define SAM_MIN_RID 1000 -#define SAM_RT_ERROR -1 -#define SAM_RT_UNIX_UID 0 -#define SAM_RT_UNIX_GID 1 -#define SAM_RT_NT_UID 2 -#define SAM_RT_NT_GID 3 -#define SAM_RT_MASK 0x3 -#define SAM_RT_EVERYONE 4 -#define SAM_RT_UNKNOWN 5 - -#define SAM_RID_TYPE(rid) ((rid) & SAM_RT_MASK) -#define SAM_DECODE_RID(rid) (((rid) - SAM_MIN_RID) >> 2) -#define SAM_ENCODE_RID(type, id) ((((id) << 2) | type) + SAM_MIN_RID) -#define SAM_ENCODE_UXUID(id) SAM_ENCODE_RID(SAM_RT_UNIX_UID, id) -#define SAM_ENCODE_UXGID(id) SAM_ENCODE_RID(SAM_RT_UNIX_GID, id) -#define SAM_ENCODE_NTUID(id) SAM_ENCODE_RID(SAM_RT_NT_UID, id) -#define SAM_ENCODE_NTGID(id) SAM_ENCODE_RID(SAM_RT_NT_GID, id) - #ifdef __cplusplus } #endif diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c index 5fb02b71f4..d131db4144 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lmshare.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -989,55 +989,6 @@ lmshare_setinfo(lmshare_info_t *si, int doshm) return (res); } -/* - * lmshare_decode_type - * - * Gets a SMB share type as an integer value and return - * a string name for it. - */ -static char * -lmshare_decode_type(uint_t stype) -{ - switch (stype) { - case STYPE_DISKTREE: - return ("Disk"); - case STYPE_PRINTQ: - return ("Print Queue"); - case STYPE_DEVICE: - return ("Device"); - case STYPE_IPC: - return ("IPC"); - case STYPE_DFS: - return ("DFS"); - case STYPE_SPECIAL: - return ("Special"); - default: - return ("Unknown"); - /* NOTREACHED */ - }; -} - -/* - * lmshare_loginfo - * - * Decodes and writes the information of the given - * share to the specified file. - */ -void -lmshare_loginfo(FILE *fp, lmshare_info_t *si) -{ - (void) fprintf(fp, "\n%s Information:\n", si->share_name); - (void) fprintf(fp, "\tFolder: %s\n", si->directory); - (void) fprintf(fp, "\tType: %s\n", - lmshare_decode_type((uint_t)si->stype)); - (void) fprintf(fp, "\tComment: %s\n", si->comment); - - (void) fprintf(fp, "\tStatus: %s\n", - ((si->mode & LMSHRM_TRANS) ? "Transient" : "Permanent")); - - (void) fprintf(fp, "\tContainer: %s\n", si->container); -} - DWORD lmshare_list(int offset, lmshare_list_t *list) { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c index 8e2effc333..4873d508cc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsalib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -32,6 +32,8 @@ #include <strings.h> #include <unistd.h> #include <netdb.h> +#include <pwd.h> +#include <grp.h> #include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> @@ -43,9 +45,111 @@ #include <smbsrv/ntsid.h> #include <smbsrv/smb_token.h> +/* + * Name Lookup modes + */ +#define MLSVC_LOOKUP_BUILTIN 1 +#define MLSVC_LOOKUP_LOCAL 2 +#define MLSVC_LOOKUP_DOMAIN 3 +#define MLSVC_LOOKUP_DOMLOC 4 + +static int lsa_lookup_mode(const char *, const char *); +static uint32_t lsa_lookup_name_builtin(char *, smb_userinfo_t *); +static uint32_t lsa_lookup_name_local(char *, char *, uint16_t, + smb_userinfo_t *); +static uint32_t lsa_lookup_name_lusr(char *, nt_sid_t **); +static uint32_t lsa_lookup_name_lgrp(char *, nt_sid_t **); +static uint32_t lsa_lookup_name_domain(char *, char *, char *, + smb_userinfo_t *); + +static uint32_t lsa_lookup_sid_builtin(nt_sid_t *, smb_userinfo_t *); +static uint32_t lsa_lookup_sid_local(nt_sid_t *, smb_userinfo_t *); +static uint32_t lsa_lookup_sid_domain(nt_sid_t *, smb_userinfo_t *); + static int lsa_list_accounts(mlsvc_handle_t *); /* + * lsa_lookup_name + * + * Lookup the given account and returns the account information + * in 'ainfo' + * + * If the name is a domain account, it may refer to a user, group or + * alias. If it is a local account, its type should be specified + * in the sid_type parameter. In case the account type is unknown + * sid_type should be set to SidTypeUnknown. + * + * account argument could be either [domain\\]name or [domain/]name. + * If domain is not specified and service is in domain mode then it + * first does a domain lookup and then a local lookup. + */ +uint32_t +lsa_lookup_name(char *server, char *account, uint16_t sid_type, + smb_userinfo_t *ainfo) +{ + nt_domain_t *dominfo; + int lookup_mode; + char *name; + char *domain; + uint32_t status = NT_STATUS_NONE_MAPPED; + + (void) strsubst(account, '\\', '/'); + name = strchr(account, '/'); + if (name) { + /* domain is specified */ + *name++ = '\0'; + domain = account; + } else { + name = account; + domain = NULL; + } + + lookup_mode = lsa_lookup_mode(domain, name); + + switch (lookup_mode) { + case MLSVC_LOOKUP_BUILTIN: + return (lsa_lookup_name_builtin(name, ainfo)); + + case MLSVC_LOOKUP_LOCAL: + return (lsa_lookup_name_local(domain, name, sid_type, ainfo)); + + case MLSVC_LOOKUP_DOMAIN: + return (lsa_lookup_name_domain(server, domain, name, ainfo)); + + default: + /* lookup the name in domain */ + dominfo = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY); + if (dominfo == NULL) + return (NT_STATUS_INTERNAL_ERROR); + status = lsa_lookup_name_domain(server, dominfo->name, name, + ainfo); + if (status != NT_STATUS_NONE_MAPPED) + return (status); + + mlsvc_release_user_info(ainfo); + /* lookup the name locally */ + status = lsa_lookup_name_local(domain, name, sid_type, ainfo); + } + + return (status); +} + +uint32_t +lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + if (!nt_sid_is_valid(sid)) + return (NT_STATUS_INVALID_SID); + + if (nt_sid_is_local(sid)) + return (lsa_lookup_sid_local(sid, ainfo)); + + if (nt_builtin_lookup_sid(sid, NULL)) + return (lsa_lookup_sid_builtin(sid, ainfo)); + + return (lsa_lookup_sid_domain(sid, ainfo)); +} + +/* * lsa_query_primary_domain_info * * Obtains the primary domain SID and name from the specified server @@ -138,174 +242,115 @@ lsa_enum_trusted_domains(void) } /* - * lsa_test_lookup - * - * Test routine for lsa_lookup_name and lsa_lookup_sid. - */ -void -lsa_test_lookup(char *name) -{ - smb_userinfo_t *user_info; - nt_sid_t *sid; - DWORD status; - smb_ntdomain_t *di; - - if ((di = smb_getdomaininfo(0)) == 0) - return; - - user_info = mlsvc_alloc_user_info(); - - if (lsa_lookup_builtin_name(name, user_info) != 0) { - status = lsa_lookup_name(di->server, di->domain, name, - user_info); - - if (status == 0) { - sid = nt_sid_splice(user_info->domain_sid, - user_info->rid); - - (void) lsa_lookup_sid(sid, user_info); - free(sid); - } - } - - mlsvc_free_user_info(user_info); -} - -/* - * lsa_lookup_builtin_name + * lsa_lookup_name_builtin * * lookup builtin account table to see if account_name is * there. If it is there, set sid_name_use, domain_sid, * domain_name, and rid fields of the passed user_info - * structure and return 0. If lookup fails return 1. + * structure. */ -int -lsa_lookup_builtin_name(char *account_name, smb_userinfo_t *user_info) +static uint32_t +lsa_lookup_name_builtin(char *account_name, smb_userinfo_t *user_info) { char *domain; int res; - user_info->domain_sid = nt_builtin_lookup_name(account_name, + user_info->user_sid = nt_builtin_lookup_name(account_name, &user_info->sid_name_use); - if (user_info->domain_sid == 0) - return (1); + if (user_info->user_sid == NULL) + return (NT_STATUS_NONE_MAPPED); + user_info->domain_sid = nt_sid_dup(user_info->user_sid); res = nt_sid_split(user_info->domain_sid, &user_info->rid); if (res < 0) - return (1); + return (NT_STATUS_INTERNAL_ERROR); domain = nt_builtin_lookup_domain(account_name); if (domain) { user_info->domain_name = strdup(domain); - return (0); + return (NT_STATUS_SUCCESS); } - return (1); + return (NT_STATUS_INTERNAL_ERROR); } /* - * lsa_lookup_local_sam + * lsa_lookup_name_local * - * lookup for the given account name in the local SAM database. - * Returns 0 on success. If lookup fails return 1. - */ -int -lsa_lookup_local_sam(char *domain, char *account_name, - smb_userinfo_t *user_info) -{ - nt_group_t *grp; - - if (*domain == '\0' || *account_name == '\0') - return (1); - - grp = nt_group_getinfo(account_name, RWLOCK_READER); - if (grp == 0) - return (1); - - user_info->sid_name_use = *grp->sid_name_use; - user_info->domain_sid = nt_sid_dup(grp->sid); - nt_group_putinfo(grp); - - if (user_info->domain_sid == 0) - return (1); - - (void) nt_sid_split(user_info->domain_sid, &user_info->rid); - user_info->domain_name = strdup(domain); - - if (user_info->domain_name == 0) { - free(user_info->domain_sid); - user_info->domain_sid = 0; - return (1); - } - - return (0); -} - -/* - * lsa_lookup_local + * 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. * - * if given account name has domain part, check to see if - * it matches with host name or any of host's primary addresses. - * if any match found first lookup in builtin accounts table and - * then in local SAM table. - * - * if account name doesn't have domain part, first do local lookups - * if nothing is found return 1. This means that caller function should - * do domain lookup. - * if any error happened return -1, if name is found return 0. + * CAVEAT: if there are both a user and a group account with + * the same name, user SID will always be returned. */ -int -lsa_lookup_local(char *name, smb_userinfo_t *user_info) +static uint32_t +lsa_lookup_name_local(char *domain, char *name, uint16_t sid_type, + smb_userinfo_t *ainfo) { char hostname[MAXHOSTNAMELEN]; - int res = 0; - int local_lookup = 0; - char *tmp; - net_cfg_t cfg; - uint32_t addr; - - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) - return (-1); - - tmp = strchr(name, '\\'); - if (tmp != 0) { - *tmp = 0; - if (strcasecmp(name, hostname) == 0) - local_lookup = 1; - - if (!local_lookup) { - addr = inet_addr(name); - if (smb_nic_get_byip(addr, &cfg) != NULL) { - local_lookup = 1; - } - } - - if (!local_lookup) { - /* do domain lookup */ - *tmp = '\\'; - return (1); - } - - name = tmp + 1; - local_lookup = 1; + nt_sid_t *sid; + uint32_t status; + + 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); } - res = lsa_lookup_builtin_name(name, user_info); - if (res != 0) - res = lsa_lookup_local_sam(hostname, name, user_info); - - if (res == 0) - return (0); + ainfo->sid_name_use = sid_type; + ainfo->user_sid = sid; + ainfo->domain_sid = nt_sid_dup(sid); + if (ainfo->domain_sid == NULL) + return (NT_STATUS_NO_MEMORY); + + (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); + if ((domain == NULL) || (*domain == '\0')) { + (void) smb_getnetbiosname(hostname, sizeof (hostname)); + ainfo->domain_name = strdup(hostname); + } else { + ainfo->domain_name = strdup(domain); + } - if (local_lookup) - return (-1); + if (ainfo->domain_name == NULL) + return (NT_STATUS_NO_MEMORY); - return (1); + return (NT_STATUS_SUCCESS); } /* - * lsa_lookup_name + * lsa_lookup_name_domain * * Lookup a name on the specified server (domain controller) and obtain * the appropriate SID. The information is returned in the user_info @@ -314,41 +359,16 @@ lsa_lookup_local(char *name, smb_userinfo_t *user_info) * type of SID. If the name is the domain name, this function will be * identical to lsa_domain_info. Otherwise the rid and name fields will * also be valid. On failure sid_name_use will be set to SidTypeUnknown. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int lsa_lookup_name(char *server, char *domain, char *account_name, - smb_userinfo_t *user_info) -{ - 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); - - rc = lsar_lookup_names(&domain_handle, account_name, user_info); - - (void) lsar_close(&domain_handle); - return (rc); -} - -/* - * lsa_lookup_name2 - * - * Returns NT status codes. */ -DWORD lsa_lookup_name2(char *server, char *domain, char *account_name, +static uint32_t +lsa_lookup_name_domain(char *server, char *domain, char *account_name, smb_userinfo_t *user_info) { mlsvc_handle_t domain_handle; - DWORD status; - int rc; char *user = smbrdr_ipc_get_user(); + uint32_t status; - rc = lsar_open(server, domain, user, &domain_handle); - if (rc != 0) + if (lsar_open(server, domain, user, &domain_handle) != 0) return (NT_STATUS_INVALID_PARAMETER); status = lsar_lookup_names2(&domain_handle, account_name, user_info); @@ -357,76 +377,8 @@ DWORD lsa_lookup_name2(char *server, char *domain, char *account_name, * Not a Windows 2000 domain controller: * use the NT compatible call. */ - if (lsar_lookup_names(&domain_handle, account_name, - user_info) != 0) - status = NT_STATUS_NONE_MAPPED; - else - status = 0; - } - - (void) lsar_close(&domain_handle); - return (status); -} - -/* - * lsa_lookup_sid - * - * Lookup a SID on the specified server (domain controller) and obtain - * the appropriate name. The information is returned in the user_info - * structure. The caller is responsible for allocating and releasing - * this structure. On success sid_name_use will be set to indicate the - * type of SID. On failure sid_name_use will be set to SidTypeUnknown. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int -lsa_lookup_sid(nt_sid_t *sid, smb_userinfo_t *user_info) -{ - mlsvc_handle_t domain_handle; - int rc; - char *user = smbrdr_ipc_get_user(); - - rc = lsar_open(NULL, NULL, user, &domain_handle); - if (rc != 0) - return (-1); - - rc = lsar_lookup_sids(&domain_handle, - (struct mslsa_sid *)sid, user_info); - - (void) lsar_close(&domain_handle); - return (rc); -} - -/* - * lsa_lookup_sid2 - * - * Returns NT status codes. - */ -DWORD -lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info) -{ - mlsvc_handle_t domain_handle; - DWORD status; - int rc; - char *user = smbrdr_ipc_get_user(); - - rc = lsar_open(NULL, NULL, user, &domain_handle); - if (rc != 0) - return (NT_STATUS_INVALID_PARAMETER); - - status = lsar_lookup_sids2(&domain_handle, - (struct mslsa_sid *)sid, user_info); - - if (status == NT_STATUS_REVISION_MISMATCH) { - /* - * Not a Windows 2000 domain controller: - * use the NT compatible call. - */ - if (lsar_lookup_sids(&domain_handle, (struct mslsa_sid *)sid, - user_info) != 0) - status = NT_STATUS_NONE_MAPPED; - else - status = 0; + status = lsar_lookup_names(&domain_handle, account_name, + user_info); } (void) lsar_close(&domain_handle); @@ -434,12 +386,12 @@ lsa_lookup_sid2(nt_sid_t *sid, smb_userinfo_t *user_info) } /* - * lsa_test_lookup2 + * lsa_test_lookup * - * Test routine for lsa_lookup_name2 and lsa_lookup_sid2. + * Test routine for lsa_lookup_name_domain and lsa_lookup_sid2. */ void -lsa_test_lookup2(char *name) +lsa_test_lookup(char *name) { smb_userinfo_t *user_info; nt_sid_t *sid; @@ -451,15 +403,15 @@ lsa_test_lookup2(char *name) user_info = mlsvc_alloc_user_info(); - if (lsa_lookup_builtin_name(name, user_info) != 0) { - status = lsa_lookup_name2(di->server, di->domain, name, + if (lsa_lookup_name_builtin(name, user_info) != 0) { + status = lsa_lookup_name_domain(di->server, di->domain, name, user_info); if (status == 0) { sid = nt_sid_splice(user_info->domain_sid, user_info->rid); - (void) lsa_lookup_sid2(sid, user_info); + (void) lsa_lookup_sid_domain(sid, user_info); free(sid); } } @@ -627,3 +579,177 @@ lsa_list_accounts(mlsvc_handle_t *domain_handle) mlsvc_free_user_info(user_info); return (0); } + +/* + * lsa_lookup_name_lusr + * + * Obtains the SID for the given local user name if it + * can be found. Upon successful return the allocated memory + * for the returned SID must be freed by the caller. + * + * Note that in domain mode this function might actually return + * a domain SID if local users are mapped to domain users. + */ +static uint32_t +lsa_lookup_name_lusr(char *name, nt_sid_t **sid) +{ + struct passwd *pw; + + if ((pw = getpwnam(name)) == NULL) + return (NT_STATUS_NO_SUCH_USER); + + if (smb_idmap_getsid(pw->pw_uid, SMB_IDMAP_USER, sid) != IDMAP_SUCCESS) + return (NT_STATUS_NONE_MAPPED); + + return (NT_STATUS_SUCCESS); +} + +/* + * lsa_lookup_name_lgrp + * + * Obtains the SID for the given local group name if it + * can be found. Upon successful return the allocated memory + * for the returned SID must be freed by the caller. + * + * Note that in domain mode this function might actually return + * a domain SID if local groups are mapped to domain groups. + */ +static uint32_t +lsa_lookup_name_lgrp(char *name, nt_sid_t **sid) +{ + struct group *gr; + + if ((gr = getgrnam(name)) == NULL) + return (NT_STATUS_NO_SUCH_ALIAS); + + if (smb_idmap_getsid(gr->gr_gid, SMB_IDMAP_GROUP, sid) != IDMAP_SUCCESS) + return (NT_STATUS_NONE_MAPPED); + + return (NT_STATUS_SUCCESS); +} + +static int +lsa_lookup_mode(const char *domain, const char *name) +{ + int lookup_mode; + + if (nt_builtin_lookup((char *)name)) + return (MLSVC_LOOKUP_BUILTIN); + + if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) + return (MLSVC_LOOKUP_LOCAL); + + if ((domain == NULL) || (*domain == '\0')) + return (MLSVC_LOOKUP_DOMLOC); + + if (mlsvc_is_local_domain(domain) == 1) + lookup_mode = MLSVC_LOOKUP_LOCAL; + else + lookup_mode = MLSVC_LOOKUP_DOMAIN; + + return (lookup_mode); +} + +static uint32_t +lsa_lookup_sid_local(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + char hostname[MAXHOSTNAMELEN]; + struct passwd *pw; + struct group *gr; + uid_t id; + int id_type; + + 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 ((pw = getpwuid(id)) == NULL) + return (NT_STATUS_NO_SUCH_USER); + + ainfo->name = strdup(pw->pw_name); + break; + + case SMB_IDMAP_GROUP: + ainfo->sid_name_use = SidTypeAlias; + if ((gr = getgrgid(id)) == NULL) + return (NT_STATUS_NO_SUCH_ALIAS); + + ainfo->name = strdup(gr->gr_name); + break; + + default: + return (NT_STATUS_NONE_MAPPED); + } + + if (ainfo->name == NULL) + return (NT_STATUS_NO_MEMORY); + + ainfo->domain_sid = nt_sid_dup(sid); + if (nt_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(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + char *name; + WORD sid_name_use; + + if ((name = nt_builtin_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 = nt_sid_dup(sid); + + if (ainfo->name == NULL || ainfo->domain_sid == NULL) + return (NT_STATUS_NO_MEMORY); + + if (sid_name_use != SidTypeDomain) + (void) nt_sid_split(ainfo->domain_sid, &ainfo->rid); + + if ((name = nt_builtin_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(nt_sid_t *sid, smb_userinfo_t *ainfo) +{ + mlsvc_handle_t domain_handle; + char *user = smbrdr_ipc_get_user(); + uint32_t status; + + if (lsar_open(NULL, NULL, user, &domain_handle) != 0) + return (NT_STATUS_INVALID_PARAMETER); + + status = lsar_lookup_sids2(&domain_handle, + (struct mslsa_sid *)sid, ainfo); + + if (status == NT_STATUS_REVISION_MISMATCH) { + /* + * Not a Windows 2000 domain controller: + * use the NT compatible call. + */ + status = lsar_lookup_sids(&domain_handle, + (struct mslsa_sid *)sid, ainfo); + } + + (void) lsar_close(&domain_handle); + return (status); +} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c index 5216818cce..f8f21e08cc 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/lsar_lookup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -175,15 +175,15 @@ lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass) * If the lookup fails, the status will typically be * NT_STATUS_NONE_MAPPED. */ -int +uint32_t lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info) { struct mlsvc_rpc_context *context; mlrpc_heapref_t heap; int opnum; - int rc; int index; + uint32_t status; struct mslsa_LookupNames arg; size_t length; lookup_name_table_t name_table; @@ -192,7 +192,7 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, char *p; if (lsa_handle == NULL || name == NULL || user_info == NULL) - return (-1); + return (NT_STATUS_INVALID_PARAMETER); bzero(user_info, sizeof (smb_userinfo_t)); user_info->sid_name_use = SidTypeUnknown; @@ -239,35 +239,39 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, name_table.name[0].str = (unsigned char *)name; (void) mlsvc_rpc_init(&heap); - rc = mlsvc_rpc_call(context, opnum, &arg, &heap); - if (rc == 0) { - if (arg.status != 0) { - rc = -1; - } else if (arg.mapped_count == 0) { - rc = -1; + if (mlsvc_rpc_call(context, opnum, &arg, &heap) != 0) { + status = NT_STATUS_INVALID_PARAMETER; + } else if (arg.status != 0) { + mlsvc_rpc_report_status(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("mlrpc", name); + + if ((index = rid_entry->domain_index) == -1) { + user_info->domain_sid = 0; + user_info->domain_name = 0; } 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("mlrpc", name); - - 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 = nt_sid_dup( - (nt_sid_t *)domain_entry->domain_sid); - user_info->domain_name = MEM_STRDUP("mlrpc", - (const char *) - domain_entry->domain_name.str); - } + domain_entry = + &arg.domain_table->entries[index]; + user_info->domain_sid = nt_sid_dup( + (nt_sid_t *)domain_entry->domain_sid); + user_info->domain_name = MEM_STRDUP("mlrpc", + (const char *) + domain_entry->domain_name.str); + user_info->user_sid = nt_sid_splice( + user_info->domain_sid, user_info->rid); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); - return (rc); + return (status); } /* @@ -279,7 +283,7 @@ lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, * level 2 but for now we want to restrict it to level 1 so that we * don't crash the PDC when we get things wrong. */ -int +uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info) { @@ -290,11 +294,11 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, struct mlsvc_rpc_context *context; mlrpc_heapref_t heap; int opnum; - int rc; int index; + uint32_t status; if (lsa_handle == NULL || sid == NULL || user_info == NULL) - return (-1); + return (NT_STATUS_INVALID_PARAMETER); context = lsa_handle->context; opnum = LSARPC_OPNUM_LookupSids; @@ -308,45 +312,48 @@ lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, arg.lup_sid_table.entries = &sid_entry; (void) mlsvc_rpc_init(&heap); - rc = mlsvc_rpc_call(context, opnum, &arg, &heap); - if (rc == 0) { - if (arg.mapped_count == 0) { - user_info->sid_name_use = SidTypeInvalid; - rc = 1; - } else { - name_entry = &arg.name_table.entries[0]; - user_info->sid_name_use = name_entry->sid_name_use; + if (mlsvc_rpc_call(context, opnum, &arg, &heap) != 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) { + mlsvc_rpc_report_status(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; - if (user_info->sid_name_use == SidTypeUser || - user_info->sid_name_use == SidTypeGroup || - user_info->sid_name_use == SidTypeAlias) { + 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]; + user_info->rid = + sid->SubAuthority[sid->SubAuthCount - 1]; - user_info->name = MEM_STRDUP("mlrpc", - (const char *)name_entry->name.str); - } + user_info->name = MEM_STRDUP("mlrpc", + (const char *)name_entry->name.str); + } - 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]; + 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]; - user_info->domain_sid = nt_sid_dup( - (nt_sid_t *)domain_entry->domain_sid); + user_info->domain_sid = nt_sid_dup( + (nt_sid_t *)domain_entry->domain_sid); - user_info->domain_name = MEM_STRDUP("mlrpc", - (const char *) - domain_entry->domain_name.str); - } + user_info->domain_name = MEM_STRDUP("mlrpc", + (const char *) + domain_entry->domain_name.str); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); - return (rc); + return (status); } /* @@ -728,8 +735,6 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, mlsvc_rpc_report_status(opnum, arg.status); status = NT_SC_VALUE(arg.status); } else { - status = 0; - name_entry = &arg.name_table.entries[0]; user_info->sid_name_use = name_entry->sid_name_use; @@ -757,6 +762,7 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, user_info->domain_name = MEM_STRDUP("mlrpc", (char const *)domain_entry->domain_name.str); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); @@ -780,7 +786,7 @@ lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, * * It should be okay to lookup DOMAIN\Administrator in this function. */ -DWORD +uint32_t lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info) { @@ -793,7 +799,7 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, lookup_name_table_t name_table; struct lsar_rid_entry2 *rid_entry; struct mslsa_domain_entry *domain_entry; - DWORD status; + uint32_t status; if (lsa_handle == NULL || name == NULL || user_info == NULL) return (NT_STATUS_INVALID_PARAMETER); @@ -831,8 +837,6 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, user_info->sid_name_use = SidTypeInvalid; status = NT_STATUS_NONE_MAPPED; } else { - status = 0; - rid_entry = &arg.translated_sids.rids[0]; user_info->sid_name_use = rid_entry->sid_name_use; user_info->rid = rid_entry->rid; @@ -849,7 +853,10 @@ lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, user_info->domain_name = MEM_STRDUP("mlrpc", (char const *)domain_entry->domain_name.str); + user_info->user_sid = nt_sid_splice( + user_info->domain_sid, user_info->rid); } + status = NT_STATUS_SUCCESS; } mlsvc_rpc_free(context, &heap); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers index a294b0ef2e..05608e27d6 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libmlsvc/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # @@ -46,41 +46,13 @@ SUNWprivate { lmshare_setinfo; lmshare_start; lmshare_stop; - lsa_lookup_name2; - lsa_lookup_sid2; lsa_query_primary_domain_info; lsa_query_account_domain_info; lsa_enum_trusted_domains; mlsvc_init; - mlsvc_is_local_domain; mlsvc_join; - nt_group_add; - nt_group_add_groupprivs; - nt_group_add_member_byname; - nt_group_cache_size; - nt_group_close_iterator; - nt_group_delete; - nt_group_del_member_byname; - nt_group_getinfo; - nt_group_getpriv; - nt_group_ht_lock; - nt_group_ht_unlock; - nt_group_is_member; - nt_group_iterate; - nt_group_modify; - nt_group_num_groups; - nt_group_num_members; - nt_group_open_iterator; - nt_group_putinfo; - nt_groups_count; - nt_group_setpriv; - nt_groups_lookup_rid; - nt_groups_member_groups; - nt_groups_member_ngroups; - nt_groups_member_privs; - nt_group_list; - nt_group_member_list; - sam_init; + mlsvc_lookup_name; + mlsvc_lookup_sid; smb_logon; smb_token_destroy; smb_build_lmshare_info; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c index de20a8c934..25acdec4f2 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -193,7 +193,7 @@ mlsvc_xa_exchange(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) struct mlndr_stream *send_mlnds = &mxa->send_mlnds; int rc; - rc = smbrdr_rpc_transact(context->fid, + rc = smbrdr_transact(context->fid, (char *)send_mlnds->pdu_base_offset, send_mlnds->pdu_size, (char *)recv_mlnds->pdu_base_offset, recv_mlnds->pdu_max_size); @@ -228,7 +228,7 @@ mlsvc_xa_read(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) if ((len = (mlnds->pdu_max_size - mlnds->pdu_size)) < 0) return (-1); - rc = smbrdr_rpc_readx(context->fid, + rc = smbrdr_readx(context->fid, (char *)mlnds->pdu_base_offset + mlnds->pdu_size, len); if (rc < 0) diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c index a20304afa8..659b184919 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_dssetup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -103,7 +103,7 @@ dssetup_DsRoleGetPrimaryDomainInfo(void *arg, struct mlrpc_xaction *mxa) } di = smb_getdomaininfo(0); - (void) smb_getdomainname(dns_domain, MAXHOSTNAMELEN); + (void) smb_getfqdomainname(dns_domain, MAXHOSTNAMELEN); if (di == NULL) { bzero(param, @@ -122,7 +122,7 @@ dssetup_DsRoleGetPrimaryDomainInfo(void *arg, struct mlrpc_xaction *mxa) (uint8_t *)MLRPC_HEAP_STRSAVE(mxa, dns_domain); param->ru.info1.forest = (uint8_t *)MLRPC_HEAP_STRSAVE(mxa, dns_domain); - bzero(¶m->ru.info1.domain_guid, sizeof (mlrpc_uuid_t)); + bzero(¶m->ru.info1.domain_guid, sizeof (ndr_uuid_t)); if (param->ru.info1.nt_domain == NULL || param->ru.info1.dns_domain == NULL || diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c deleted file mode 100644 index a13b7346f5..0000000000 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_handle.c +++ /dev/null @@ -1,179 +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. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This module provides the handles used in the various server-side - * RPC functions. I don't think other systems care about the value in - * the handle. It should be treated as an opaque data block. Handles - * are issued when a service is opened and obsoleted when it is closed. - * We should check incoming RPC requests to ensure that the handle - * being used is associated with the particular service being accessed. - */ - -#include <strings.h> -#include <unistd.h> -#include <assert.h> - -#include <smbsrv/libsmb.h> -#include <smbsrv/mlsvc_util.h> -#include <smbsrv/ntsid.h> - -/* - * Each time a handle is allocated it is added to the global handle - * descriptor list because we need some way of identifying the - * interface and domain to which the handle was assigned when it is - * returned on a subsequent RPC. - */ -ms_handle_t mlsvc_handle; -ms_handle_desc_t *mlsvc_desc_list; - -/* - * mlsvc_get_handle - * - * This function returns a handle for use with the server-side RPC - * functions. Every time it is called it will increment the handle - * value and return a pointer to it. On NT, handle[0] always seems - * to be zero and handle[1] increments. The rest seems to be some - * sort of unique value so the local domain SID should do. - * - * The handle is added to the global handle descriptor list with the - * designated ifspec and key tag. - */ -ms_handle_t * -mlsvc_get_handle(ms_ifspec_t ifspec, char *key, DWORD discrim) -{ - ms_handle_desc_t *desc; - nt_sid_t *sid; - - if ((desc = malloc(sizeof (ms_handle_desc_t))) == NULL) - assert(desc); - - sid = nt_domain_local_sid(); - if (mlsvc_handle.handle[1] == 0) { - mlsvc_handle.handle[0] = 0; - mlsvc_handle.handle[1] = 0; - mlsvc_handle.handle[2] = sid->SubAuthority[1]; - mlsvc_handle.handle[3] = sid->SubAuthority[2]; - mlsvc_handle.handle[4] = sid->SubAuthority[3]; - } - - ++mlsvc_handle.handle[1]; - - bcopy(&mlsvc_handle, &desc->handle, sizeof (ms_handle_t)); - desc->ifspec = ifspec; - desc->discrim = discrim; - desc->next = mlsvc_desc_list; - mlsvc_desc_list = desc; - - if (key) - (void) strlcpy(desc->key, key, MLSVC_HANDLE_KEY_MAX); - else - desc->key[0] = '\0'; - - return (&mlsvc_handle); -} - - -/* - * mlsvc_put_handle - * - * Remove a handle from the global handle descriptor list and free the - * memory it was using. If the list contained the descriptor, a value - * of 0 is returned. Otherwise -1 is returned. - */ -int -mlsvc_put_handle(ms_handle_t *handle) -{ - ms_handle_desc_t *desc; - ms_handle_desc_t **ppdesc = &mlsvc_desc_list; - - assert(handle); - - while (*ppdesc) { - desc = *ppdesc; - - if (bcmp(&desc->handle, handle, sizeof (ms_handle_t)) == 0) { - *ppdesc = desc->next; - free(desc); - return (0); - } - - ppdesc = &(*ppdesc)->next; - } - - return (-1); -} - - -/* - * mlsvc_validate_handle - * - * Lookup a handle in the global handle descriptor list. If the handle - * is in the list, a pointer to the descriptor is returned. Otherwise - * a null pointer is returned. - */ -int -mlsvc_validate_handle(ms_handle_t *handle, char *key) -{ - ms_handle_desc_t *desc; - - assert(handle); - assert(key); - - if ((desc = mlsvc_lookup_handle(handle)) == 0) - return (NULL); - - if (strcmp(desc->key, key)) - return (NULL); - - return (1); -} - - -/* - * mlsvc_lookup_handle - * - * Lookup a handle in the global handle descriptor list. If the handle - * is in the list, a pointer to the descriptor is returned. Otherwise - * a null pointer is returned. - */ -ms_handle_desc_t * -mlsvc_lookup_handle(ms_handle_t *handle) -{ - ms_handle_desc_t *desc = mlsvc_desc_list; - - assert(handle); - - while (desc) { - if (bcmp(&desc->handle, handle, sizeof (ms_handle_t)) == 0) - return (desc); - - desc = desc->next; - } - - return (NULL); -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c index fc17554949..cd8ec7da36 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_init.c @@ -19,19 +19,15 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" -#include <stdio.h> #include <unistd.h> - -#include <smbsrv/libsmb.h> +#include <pthread.h> #include <smbsrv/libmlsvc.h> -#include <smbsrv/mlsvc_util.h> -#include <smbsrv/lsalib.h> void dssetup_initialize(void); void srvsvc_initialize(void); @@ -42,6 +38,12 @@ void netr_initialize(void); void samr_initialize(void); void svcctl_initialize(void); void winreg_initialize(void); +int srvsvc_gettime(unsigned long *); + +static void *mlsvc_keepalive(void *); + +static pthread_t mlsvc_keepalive_thr; +#define MLSVC_KEEPALIVE_INTERVAL (10 * 60) /* 10 minutes */ /* * All mlrpc initialization is invoked from here. @@ -50,6 +52,9 @@ void winreg_initialize(void); int mlsvc_init(void) { + pthread_attr_t tattr; + int rc; + srvsvc_initialize(); wkssvc_initialize(); lsarpc_initialize(); @@ -60,6 +65,35 @@ mlsvc_init(void) winreg_initialize(); logr_initialize(); - (void) sam_init(); - return (0); + (void) lsa_query_primary_domain_info(); + + (void) pthread_attr_init(&tattr); + (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); + rc = pthread_create(&mlsvc_keepalive_thr, &tattr, + mlsvc_keepalive, 0); + (void) pthread_attr_destroy(&tattr); + return (rc); +} + +/*ARGSUSED*/ +static void * +mlsvc_keepalive(void *arg) +{ + unsigned long t; + nt_domain_t *domain; + + for (;;) { + (void) sleep(MLSVC_KEEPALIVE_INTERVAL); + + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { + domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY); + if (domain == NULL) + (void) lsa_query_primary_domain_info(); + } + + (void) srvsvc_gettime(&t); + } + + /*NOTREACHED*/ + return (NULL); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c index 4a6c80613d..3070561173 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_logr.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -195,7 +195,6 @@ typedef struct { } read_data_t; static char logr_sysname[SYS_NMLN]; -static char hostname[MAXHOSTNAMELEN]; static mts_wchar_t wcs_hostname[MAXHOSTNAMELEN]; static int hostname_len = 0; static mts_wchar_t wcs_srcname[MAX_SRCNAME_LEN]; @@ -231,26 +230,25 @@ logr_initialize(void) /* * logr_s_EventLogClose * - * This is a request to close the LOGR interface specified by the - * handle. Free the handle and its associated resources and zero out - * the result handle for the client. + * This is a request to close the LOGR interface specified by handle. + * Free the handle and associated resources, and zero out the result + * handle for the client. */ -/*ARGSUSED*/ static int logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogClose *param = arg; - ms_handle_desc_t *desc; - read_data_t *data; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; - if ((desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle)) == 0) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { + bzero(¶m->result_handle, sizeof (logr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - data = (read_data_t *)(uintptr_t)(desc->discrim); - free(data); - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); + free(hd->nh_data); + ndr_hdfree(mxa, id); bzero(¶m->result_handle, sizeof (logr_handle_t)); param->status = NT_STATUS_SUCCESS; @@ -260,40 +258,16 @@ logr_s_EventLogClose(void *arg, struct mlrpc_xaction *mxa) /* * logr_s_EventLogOpen * - * This is a request to open the event log. - * - * Return a handle for use with subsequent event log requests. + * Open the event log. Not supported yet. */ /*ARGSUSED*/ static int logr_s_EventLogOpen(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogOpen *param = arg; - ms_handle_t *handle; - int log_enable = 0; - int len; - int rc; - smb_config_rdlock(); - log_enable = smb_config_getyorn(SMB_CI_LOGR_ENABLE); - smb_config_unlock(); - - rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - - if (log_enable == 0 || rc != 0) { - bzero(¶m->handle, sizeof (logr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } - - handle = mlsvc_get_handle(MLSVC_IFSPEC_LOGR, LOGR_KEY, 0); - bcopy(handle, ¶m->handle, sizeof (logr_handle_t)); - - len = strlen(hostname) + 1; - (void) mts_mbstowcs(wcs_hostname, hostname, len); - hostname_len = len * sizeof (mts_wchar_t); - - param->status = NT_STATUS_SUCCESS; + bzero(¶m->handle, sizeof (logr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } @@ -316,15 +290,15 @@ logr_get_snapshot(void) * return number of log entries in the snapshot as result of RPC * call. */ -/*ARGSUSED*/ static int logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogQueryCount *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *data; - if ((desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle)) == 0) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } @@ -334,7 +308,7 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)(uintptr_t)data; + hd->nh_data = data; param->rec_num = data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -345,21 +319,20 @@ logr_s_EventLogQueryCount(void *arg, struct mlrpc_xaction *mxa) * * Return oldest record number in the snapshot as result of RPC call. */ -/*ARGSUSED*/ static int logr_s_EventLogGetOldestRec(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogGetOldestRec *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *data; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == NULL) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - data = (read_data_t *)(uintptr_t)desc->discrim; + data = (read_data_t *)hd->nh_data; param->oldest_rec = data->log.ix - data->tot_recnum; param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); @@ -452,12 +425,12 @@ set_logrec(log_entry_t *le, DWORD recno, logr_record_t *rec) * Reads a whole number of entries from system log. The function can * read log entries in chronological or reverse chronological order. */ -/*ARGSUSED*/ static int logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa) { struct logr_EventLogRead *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; read_data_t *rdata; log_entry_t *le; DWORD ent_no, ent_num, ent_remain; @@ -465,20 +438,19 @@ logr_s_EventLogRead(void *arg, struct mlrpc_xaction *mxa) BYTE *buf; int dir, ent_per_req; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == NULL) { + if ((hd = ndr_hdlookup(mxa, id)) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - rdata = (read_data_t *)(uintptr_t)(desc->discrim); - if (rdata == 0) { + rdata = (read_data_t *)hd->nh_data; + if (rdata == NULL) { if ((rdata = logr_get_snapshot()) == NULL) { param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); return (MLRPC_DRC_OK); } - desc->discrim = (DWORD)(uintptr_t)rdata; + hd->nh_data = rdata; } dir = (param->read_flags & EVENTLOG_FORWARDS_READ) ? FWD : REW; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c index 4d770edbc1..0bc4206f3d 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_lsa.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -54,6 +54,9 @@ struct local_group_table { char *name; }; +static int lsarpc_key_domain; +static int lsarpc_key_account; + static int lsarpc_call_stub(struct mlrpc_xaction *mxa); static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *); @@ -78,14 +81,6 @@ static int lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *, struct mlrpc_xaction *); static int lsarpc_s_AccountDomainInfo(struct mslsa_AccountDomainInfo *, struct mlrpc_xaction *); -static int lsarpc_s_LookupNtSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *, int); -static int lsarpc_s_LookupLocalSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); -static int lsarpc_s_LookupBuiltinSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); -static int lsarpc_s_UnknownSid(struct mlrpc_xaction *, nt_sid_t *, - smb_userinfo_t *, struct mslsa_name_entry *); static int lsarpc_s_UpdateDomainTable(struct mlrpc_xaction *, smb_userinfo_t *, struct mslsa_domain_table *, DWORD *); @@ -177,22 +172,21 @@ lsarpc_call_stub(struct mlrpc_xaction *mxa) * lsarpc_s_OpenDomainHandle opnum=0x06 * * This is a request to open the LSA (OpenPolicy and OpenPolicy2). - * The client is looking for an LSA domain handle. Handles appear to - * be a 20 byte opaque object with the top 4 bytes all zero. As it is - * opaque to the client, we can put anything we like in it. Real handles - * do appear to contain a sequence number which is incremented when a - * new handle is issued. However, we don't really care about that - * (yet). Always return MLRPC_DRC_OK. + * The client is looking for an LSA domain handle. */ -/*ARGSUSED*/ static int lsarpc_s_OpenDomainHandle(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_OpenPolicy2 *param = arg; + ndr_hdid_t *id; - bzero(¶m->domain_handle, sizeof (mslsa_handle_t)); - (void) strcpy((char *)¶m->domain_handle.hand2, "DomainHandle"); - param->status = 0; + if ((id = ndr_hdalloc(mxa, &lsarpc_key_domain)) != NULL) { + bcopy(id, ¶m->domain_handle, sizeof (mslsa_handle_t)); + param->status = NT_STATUS_SUCCESS; + } else { + bzero(¶m->domain_handle, sizeof (mslsa_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } return (MLRPC_DRC_OK); } @@ -205,15 +199,16 @@ lsarpc_s_OpenDomainHandle(void *arg, struct mlrpc_xaction *mxa) * MLRPC_DRC_OK. Setting the handle to zero appears to be standard * behaviour and someone may rely on it, i.e. we do on the client side. */ -/*ARGSUSED*/ static int lsarpc_s_CloseHandle(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_CloseHandle *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - bzero(¶m->result_handle, sizeof (param->result_handle)); - param->status = 0; + ndr_hdfree(mxa, id); + bzero(¶m->result_handle, sizeof (param->result_handle)); + param->status = NT_STATUS_SUCCESS; return (MLRPC_DRC_OK); } @@ -307,23 +302,28 @@ lsarpc_s_EnumTrustedDomain(void *arg, struct mlrpc_xaction *mxa) /* * lsarpc_s_OpenAccount * - * This is a request to open an account handle. This function hasn't - * been tested. It is just a template in case some server somewhere - * makes this call. See lsarpc_s_OpenDomainHandle for more information. + * This is a request to open an account handle. */ -/*ARGSUSED*/ static int lsarpc_s_OpenAccount(void *arg, struct mlrpc_xaction *mxa) { struct mslsa_OpenAccount *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &lsarpc_key_domain)) { + bzero(¶m, sizeof (struct mslsa_OpenAccount)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } - if (param->handle.hand1 != 0 || - strcmp("DomainHandle", (char *)¶m->handle.hand2)) { - param->status = NT_SC_ERROR(ERROR_NO_SUCH_DOMAIN); + if ((id = ndr_hdalloc(mxa, &lsarpc_key_account)) != NULL) { + bcopy(id, ¶m->account_handle, sizeof (mslsa_handle_t)); + param->status = NT_STATUS_SUCCESS; } else { - (void) strcpy((char *)¶m->account_handle.hand2, - "AccountHandle"); - param->status = 0; + bzero(¶m->account_handle, sizeof (mslsa_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); } return (MLRPC_DRC_OK); @@ -584,7 +584,7 @@ lsarpc_s_PrimaryDomainInfo(struct mslsa_PrimaryDomainInfo *pd_info, status = NT_STATUS_SUCCESS; - security_mode = smb_get_security_mode(); + security_mode = smb_config_get_secmode(); if (security_mode != SMB_SECMODE_DOMAIN) { rc = smb_gethostname(domain_name, MLSVC_DOMAIN_NAME_MAX, 1); @@ -686,8 +686,8 @@ lsarpc_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) smb_userinfo_t *user_info = 0; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; - char *name = ""; DWORD status = NT_STATUS_SUCCESS; + char *account; int rc = 0; if (param->name_table->n_entry != 1) @@ -704,20 +704,10 @@ lsarpc_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) goto name_lookup_failed; } - name = (char *)param->name_table->names->str; - - rc = lsa_lookup_local(name, user_info); - if (rc < 0) { - status = NT_STATUS_NO_SUCH_USER; + account = (char *)param->name_table->names->str; + status = lsa_lookup_name(NULL, account, SidTypeUnknown, user_info); + if (status != NT_STATUS_SUCCESS) goto name_lookup_failed; - } - - if (rc > 0) { - if (lsa_lookup_name(0, 0, name, user_info) != 0) { - status = NT_STATUS_NO_SUCH_USER; - goto name_lookup_failed; - } - } /* * Set up the rid table. @@ -780,6 +770,7 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; struct mslsa_name_entry *names; + struct mslsa_name_entry *name; smb_userinfo_t *user_info; nt_sid_t *sid; DWORD n_entry; @@ -805,48 +796,28 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) domain_table->n_entry = 0; domain_table->max_n_entry = MLSVC_DOMAIN_MAX; - for (i = 0; i < n_entry; ++i) { + name = names; + for (i = 0; i < n_entry; ++i, name++) { bzero(&names[i], sizeof (struct mslsa_name_entry)); sid = (nt_sid_t *)param->lup_sid_table.entries[i].psid; - if (nt_sid_is_local(sid)) { - result = lsarpc_s_LookupLocalSid(mxa, sid, user_info, - &names[i]); - } else { - result = lsarpc_s_LookupBuiltinSid(mxa, sid, user_info, - &names[i]); - - if (result != 0) - result = lsarpc_s_LookupNtSid(mxa, sid, - user_info, &names[i], 1); + result = lsa_lookup_sid(sid, user_info); + if (result != NT_STATUS_SUCCESS) + goto lookup_sid_failed; - if (result != 0) { - result = lsarpc_s_UnknownSid(mxa, sid, - user_info, &names[i]); - } - } - - if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + if (!mlsvc_string_save((ms_string_t *)&name->name, + user_info->name, mxa)) { + result = NT_STATUS_NO_MEMORY; + goto lookup_sid_failed; } + name->sid_name_use = user_info->sid_name_use; result = lsarpc_s_UpdateDomainTable(mxa, user_info, - domain_table, &names[i].domain_ix); + domain_table, &name->domain_ix); if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + result = NT_STATUS_INTERNAL_ERROR; + goto lookup_sid_failed; } mlsvc_release_user_info(user_info); @@ -860,295 +831,16 @@ lsarpc_s_LookupSids(void *arg, struct mlrpc_xaction *mxa) mlsvc_free_user_info(user_info); return (MLRPC_DRC_OK); -} - -/* - * lsarpc_s_LookupLocalSid - * - * This function handles local domain SID lookup. If the SID matches the - * local domain SID, we lookup the local files to map the RID to a name. - * We attempt to handle both users and groups. When the SID was supplied - * to the client, the ID type should have been encoded in the RID. We - * decode the RID and lookup it up in either the passwd file or the - * group file as appropriate. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_LookupLocalSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char buffer[MLSVC_DOMAIN_NAME_MAX]; - char namebuf[MLSVC_DOMAIN_NAME_MAX]; - nt_sid_t *lds; - nt_sid_t *tmp_sid; - nt_group_t *grp; - struct passwd *pw; - struct group *gr; - DWORD rid; - int unix_id; - - if (smb_gethostname(buffer, MLSVC_DOMAIN_NAME_MAX, 1) != 0) - return (-1); - - /* - * Only free tmp_sid in error paths. If it is assigned to the - * user_info, it will be freed later when that structure is - * released. - */ - if ((tmp_sid = nt_sid_dup(sid)) == NULL) - return (-1); - - rid = 0; - lds = nt_domain_local_sid(); - user_info->sid_name_use = SidTypeInvalid; - - if (nt_sid_is_equal(lds, tmp_sid)) { - user_info->sid_name_use = SidTypeDomain; - user_info->name = strdup(buffer); - } else { - (void) nt_sid_split(tmp_sid, &rid); - - switch (SAM_RID_TYPE(rid)) { - case SAM_RT_NT_UID: - break; - - case SAM_RT_NT_GID: - user_info->sid_name_use = SidTypeAlias; - grp = nt_groups_lookup_rid(rid); - if (grp) - user_info->name = strdup(grp->name); - else { - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", rid); - user_info->name = strdup(namebuf); - } - break; - - case SAM_RT_UNIX_UID: - /* - * It is always possible that the rid will not - * correspond to an entry in the local passwd or group - * file. In this case we can return the RID with a - * message to indicate the problem, which seems better - * than returning an invalid SID error. - */ - unix_id = SAM_DECODE_RID(rid); - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", unix_id); - user_info->sid_name_use = SidTypeUser; - pw = getpwuid(unix_id); - user_info->name = (pw) ? - strdup(pw->pw_name) : strdup(namebuf); - break; - - case SAM_RT_UNIX_GID: - unix_id = SAM_DECODE_RID(rid); - (void) snprintf(namebuf, sizeof (namebuf), - "%d (no name)", unix_id); - user_info->sid_name_use = SidTypeAlias; - gr = getgrgid(unix_id); - user_info->name = (gr) ? - strdup(gr->gr_name) : strdup(namebuf); - break; - } - } - - if (user_info->sid_name_use == SidTypeInvalid) { - free(tmp_sid); - return (-1); - } - /* - * Set up the rest of user_info. - * Don't free tmp_sid after this. - */ - user_info->rid = rid; - user_info->domain_name = strdup(buffer); - user_info->domain_sid = tmp_sid; - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - return (-1); - } +lookup_sid_failed: + param->domain_table = 0; + param->name_table.n_entry = 0; + param->name_table.entries = 0; + param->mapped_count = 0; + param->status = NT_SC_ERROR(result); - return (0); -} - -/* - * lsarpc_s_LookupNtSid - * - * This function handles NT domain SID lookup on the domain controller. - * Most of the work is performed by lsa_lookup_sid. We just have to - * update the name data for the response. It is assumed that any SID - * passed to this function has already been checked and correctly - * identified as an NT domain SID. It shouldn't break anything if you - * get it wrong, the domain controller will just reject the SID. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_LookupNtSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name, int version) -{ - char *username; - DWORD status; - - if (smb_getdomaininfo(0) == 0) { - status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - return (-1); - } - - if (version == 2) - status = lsa_lookup_sid2(sid, user_info); - else - status = lsa_lookup_sid(sid, user_info); - - if (status != 0) - return (-1); - - switch (user_info->sid_name_use) { - case SidTypeDomain: - if ((username = user_info->domain_name) == 0) - user_info->sid_name_use = SidTypeUnknown; - break; - - case SidTypeUser: - case SidTypeGroup: - case SidTypeAlias: - case SidTypeDeletedAccount: - case SidTypeWellKnownGroup: - if ((username = user_info->name) == 0) - user_info->sid_name_use = SidTypeUnknown; - break; - - default: - return (-1); - } - - if (username == 0) - username = "unknown"; - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save((ms_string_t *)&name->name, username, mxa)) - return (-1); - - return (0); -} - -/* - * lsarpc_s_LookupBuiltinSid - * - * This function handles predefined local groups and aliases in the NT - * AUTHORITY or BUILTIN domains, and some other miscellaneous bits. I - * don't think NT cares about the domain field of well-known groups or - * aliases but it seems sensible to set it up anyway. If we get a match, - * set up the name in the response heap. - * - * On success, 0 is returned. Otherwise non-zero is returned. A non-zero - * return value should not be automatically interpreted as an error. The - * caller should attempt to resolve the SID through alternative means. - */ -static int -lsarpc_s_LookupBuiltinSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char *np; - WORD sid_name_use; - - if ((np = nt_builtin_lookup_sid(sid, &sid_name_use)) == NULL) - return (1); - - user_info->sid_name_use = sid_name_use; - user_info->name = strdup(np); - user_info->domain_sid = nt_sid_dup(sid); - - if (user_info->name == NULL || user_info->domain_sid == NULL) { - mlsvc_release_user_info(user_info); - return (-1); - } - - if (sid_name_use != SidTypeDomain && sid->SubAuthCount != 0) - user_info->rid = sid->SubAuthority[sid->SubAuthCount - 1]; - else - user_info->rid = 0; - - if ((np = nt_builtin_lookup_domain(user_info->name)) != NULL) - user_info->domain_name = strdup(np); - else - user_info->domain_name = strdup("UNKNOWN"); - - if (user_info->domain_name == NULL) { - mlsvc_release_user_info(user_info); - return (-1); - } - - if (sid_name_use == SidTypeAlias && - user_info->domain_sid->SubAuthCount != 0) { - --user_info->domain_sid->SubAuthCount; - } - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = sid_name_use; - - if (sid_name_use == SidTypeUnknown) { - mlsvc_release_user_info(user_info); - return (1); - } - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - mlsvc_release_user_info(user_info); - return (-1); - } - - return (0); -} - -/* - * lsarpc_s_UnknownSid - * - * This function handles unknown SIDs. By the time this is called we - * know that this is not a local SID and that the PDC has no idea to - * whom this sid refers. It may be a remnant from a time when the - * server was in another domain. All we can do is turn into the SID - * into a string and return it in place of a user name. - * - * On success, 0 is returned. Otherwise -1 is returned. - */ -static int -lsarpc_s_UnknownSid(struct mlrpc_xaction *mxa, nt_sid_t *sid, - smb_userinfo_t *user_info, struct mslsa_name_entry *name) -{ - char domain_name[MLSVC_DOMAIN_NAME_MAX]; - char *sidbuf; - - if ((sidbuf = nt_sid_format(sid)) == NULL) - return (-1); - - if (smb_gethostname(domain_name, MLSVC_DOMAIN_NAME_MAX, 1) != 0) - return (-1); - - (void) utf8_strupr(domain_name); - mlsvc_release_user_info(user_info); - user_info->sid_name_use = SidTypeUnknown; - user_info->name = sidbuf; - user_info->domain_name = strdup(domain_name); - user_info->domain_sid = nt_sid_dup(nt_domain_local_sid()); - - bzero(name, sizeof (struct mslsa_name_entry)); - name->sid_name_use = user_info->sid_name_use; - - if (!mlsvc_string_save( - (ms_string_t *)&name->name, user_info->name, mxa)) { - return (-1); - } - - return (0); + mlsvc_free_user_info(user_info); + return (MLRPC_DRC_OK); } /* @@ -1223,6 +915,7 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) { struct lsar_lookup_sids2 *param = arg; struct lsar_name_entry2 *names; + struct lsar_name_entry2 *name; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; smb_userinfo_t *user_info; @@ -1250,51 +943,28 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) domain_table->n_entry = 0; domain_table->max_n_entry = MLSVC_DOMAIN_MAX; - for (i = 0; i < n_entry; ++i) { - bzero(&names[i], sizeof (struct lsar_name_entry2)); + name = names; + for (i = 0; i < n_entry; ++i, name++) { + bzero(name, sizeof (struct lsar_name_entry2)); sid = (nt_sid_t *)param->lup_sid_table.entries[i].psid; - if (nt_sid_is_local(sid)) { - result = lsarpc_s_LookupLocalSid(mxa, sid, user_info, - (struct mslsa_name_entry *)&names[i]); - } else { - result = lsarpc_s_LookupBuiltinSid(mxa, sid, user_info, - (struct mslsa_name_entry *)&names[i]); - - if (result != 0) - result = lsarpc_s_LookupNtSid(mxa, sid, - user_info, - (struct mslsa_name_entry *)&names[i], 2); - - if (result != 0) { - result = lsarpc_s_UnknownSid(mxa, sid, - user_info, - (struct mslsa_name_entry *)&names[i]); - } - } + result = lsa_lookup_sid(sid, user_info); + if (result != NT_STATUS_SUCCESS) + goto lookup_sid_failed; - if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - return (MLRPC_DRC_OK); + if (!mlsvc_string_save((ms_string_t *)&name->name, + user_info->name, mxa)) { + result = NT_STATUS_NO_MEMORY; + goto lookup_sid_failed; } + name->sid_name_use = user_info->sid_name_use; result = lsarpc_s_UpdateDomainTable(mxa, user_info, - domain_table, &names[i].domain_ix); + domain_table, &name->domain_ix); if (result == -1) { - mlsvc_free_user_info(user_info); - param->domain_table = 0; - param->name_table.n_entry = 0; - param->name_table.entries = 0; - param->mapped_count = 0; - param->status = NT_SC_ERROR(NT_STATUS_INVALID_SID); - - return (MLRPC_DRC_OK); + result = NT_STATUS_INTERNAL_ERROR; + goto lookup_sid_failed; } mlsvc_release_user_info(user_info); @@ -1308,6 +978,16 @@ lsarpc_s_LookupSids2(void *arg, struct mlrpc_xaction *mxa) mlsvc_free_user_info(user_info); return (MLRPC_DRC_OK); + +lookup_sid_failed: + param->domain_table = 0; + param->name_table.n_entry = 0; + param->name_table.entries = 0; + param->mapped_count = 0; + param->status = NT_SC_ERROR(result); + + mlsvc_free_user_info(user_info); + return (MLRPC_DRC_OK); } /* @@ -1324,7 +1004,7 @@ lsarpc_s_LookupNames2(void *arg, struct mlrpc_xaction *mxa) smb_userinfo_t *user_info = 0; struct mslsa_domain_table *domain_table; struct mslsa_domain_entry *domain_entry; - char *name = ""; + char *account; DWORD status = NT_STATUS_SUCCESS; int rc = 0; @@ -1342,20 +1022,10 @@ lsarpc_s_LookupNames2(void *arg, struct mlrpc_xaction *mxa) goto name_lookup2_failed; } - name = (char *)param->name_table->names->str; - - rc = lsa_lookup_local(name, user_info); - if (rc < 0) { - status = NT_STATUS_NONE_MAPPED; + account = (char *)param->name_table->names->str; + status = lsa_lookup_name(NULL, account, SidTypeUnknown, user_info); + if (status != NT_STATUS_SUCCESS) goto name_lookup2_failed; - } - - if (rc > 0) { - if (lsa_lookup_name2(0, 0, name, user_info) != 0) { - status = NT_STATUS_NONE_MAPPED; - goto name_lookup2_failed; - } - } /* * Set up the rid table. diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c index 6d22e62127..3be04d2a50 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_sam.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,28 +47,31 @@ #include <smbsrv/samlib.h> /* - * The keys associated with the various handles dispensed - * by the SAMR server. These keys can be used to validate - * client activity. These values are never passed over - * the network so security shouldn't be an issue. + * The keys associated with the various handles dispensed by the SAMR + * server. These keys can be used to validate client activity. + * These values are never passed over the wire so security shouldn't + * be an issue. */ -#define SAMR_CONNECT_KEY "SamrConnect" -#define SAMR_DOMAIN_KEY "SamrDomain" -#define SAMR_USER_KEY "SamrUser" -#define SAMR_GROUP_KEY "SamrGroup" -#define SAMR_ALIAS_KEY "SamrAlias" - -/* - * Domain discriminator values. Set the top bit to try - * to distinguish these values from user and group ids. - */ -#define SAMR_DATABASE_DOMAIN 0x80000001 -#define SAMR_LOCAL_DOMAIN 0x80000002 -#define SAMR_BUILTIN_DOMAIN 0x80000003 -#define SAMR_PRIMARY_DOMAIN 0x80000004 - +typedef enum { + SAMR_KEY_NULL = 0, + SAMR_KEY_CONNECT, + SAMR_KEY_DOMAIN, + SAMR_KEY_USER, + SAMR_KEY_GROUP, + SAMR_KEY_ALIAS +} samr_key_t; + +typedef struct samr_keydata { + samr_key_t kd_key; + nt_domain_type_t kd_type; + DWORD kd_rid; +} samr_keydata_t; + +static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, nt_domain_type_t, + DWORD); +static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *); +static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t); static int samr_call_stub(struct mlrpc_xaction *mxa); - static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *, struct mlrpc_xaction *); @@ -115,6 +118,60 @@ samr_call_stub(struct mlrpc_xaction *mxa) } /* + * Handle allocation wrapper to setup the local context. + */ +static ndr_hdid_t * +samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, nt_domain_type_t domain_type, + DWORD rid) +{ + samr_keydata_t *data; + + if ((data = malloc(sizeof (samr_keydata_t))) == NULL) + return (NULL); + + data->kd_key = key; + data->kd_type = domain_type; + data->kd_rid = rid; + + return (ndr_hdalloc(mxa, data)); +} + +/* + * Handle deallocation wrapper to free the local context. + */ +static void +samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id) +{ + ndr_handle_t *hd; + + if ((hd = ndr_hdlookup(mxa, id)) != NULL) { + free(hd->nh_data); + ndr_hdfree(mxa, id); + } +} + +/* + * Handle lookup wrapper to validate the local context. + */ +static ndr_handle_t * +samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key) +{ + ndr_handle_t *hd; + samr_keydata_t *data; + + if ((hd = ndr_hdlookup(mxa, id)) == NULL) + return (NULL); + + if ((data = (samr_keydata_t *)hd->nh_data) == NULL) + return (NULL); + + if (data->kd_key != key) + return (NULL); + + return (hd); +} + +/* * samr_s_ConnectAnon * * This is a request to connect to the local SAM database. We don't @@ -124,44 +181,38 @@ samr_call_stub(struct mlrpc_xaction *mxa) * * Return a handle for use with subsequent SAM requests. */ -/*ARGSUSED*/ static int samr_s_ConnectAnon(void *arg, struct mlrpc_xaction *mxa) { struct samr_ConnectAnon *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_CONNECT_KEY, - SAMR_DATABASE_DOMAIN); - bcopy(handle, ¶m->handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + if (id) { + bcopy(id, ¶m->handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } /* * samr_s_CloseHandle * - * This is a request to close the SAM interface specified by the handle. + * Close the SAM interface specified by the handle. * Free the handle and zero out the result handle for the client. - * - * We could do some checking here but it probably doesn't matter. */ -/*ARGSUSED*/ static int samr_s_CloseHandle(void *arg, struct mlrpc_xaction *mxa) { struct samr_CloseHandle *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; -#ifdef SAMR_S_DEBUG - if (mlsvc_lookup_handle((ms_handle_t *)¶m->handle) == 0) { - bzero(¶m->result_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - return (MLRPC_DRC_OK); - } -#endif /* SAMR_S_DEBUG */ + samr_hdfree(mxa, id); - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); bzero(¶m->result_handle, sizeof (samr_handle_t)); param->status = 0; return (MLRPC_DRC_OK); @@ -179,9 +230,8 @@ static int samr_s_LookupDomain(void *arg, struct mlrpc_xaction *mxa) { struct samr_LookupDomain *param = arg; - char resource_domain[MAXHOSTNAMELEN]; + char resource_domain[SMB_PI_MAX_DOMAIN]; char *domain_name; - char *p; nt_sid_t *sid = NULL; if ((domain_name = (char *)param->domain_name.str) == NULL) { @@ -190,11 +240,7 @@ samr_s_LookupDomain(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_DOMAIN_NAME); - (void) strlcpy(resource_domain, p, MAXHOSTNAMELEN); - smb_config_unlock(); - + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); if (mlsvc_is_local_domain(domain_name) == 1) { sid = nt_sid_dup(nt_domain_local_sid()); } else if (strcasecmp(resource_domain, domain_name) == 0) { @@ -237,12 +283,10 @@ static int samr_s_EnumLocalDomains(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumLocalDomain *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; DWORD status; - handle = (ms_handle_t *)¶m->handle; - - if (mlsvc_validate_handle(handle, SAMR_CONNECT_KEY) == 0) + if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) status = NT_STATUS_ACCESS_DENIED; else status = samr_s_enum_local_domains(param, mxa); @@ -308,52 +352,42 @@ samr_s_enum_local_domains(struct samr_EnumLocalDomain *param, * samr_s_OpenDomain * * This is a request to open a domain within the local SAM database. - * The caller must supply a valid handle obtained via a successful - * connect. We return a handle to be used to access objects within - * this domain. + * The caller must supply a valid connect handle. + * We return a handle to be used to access objects within this domain. */ -/*ARGSUSED*/ static int samr_s_OpenDomain(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenDomain *param = arg; - ms_handle_t *handle = 0; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; nt_domain_t *domain; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_CONNECT_KEY)) { + if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } - domain = nt_domain_lookup_sid((nt_sid_t *)param->sid); - if (domain == NULL) { + if ((domain = nt_domain_lookup_sid((nt_sid_t *)param->sid)) == NULL) { bzero(¶m->domain_handle, sizeof (samr_handle_t)); param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); return (MLRPC_DRC_OK); } - switch (domain->type) { - case NT_DOMAIN_BUILTIN: - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_DOMAIN_KEY, SAMR_BUILTIN_DOMAIN); - - bcopy(handle, ¶m->domain_handle, sizeof (samr_handle_t)); - param->status = 0; - break; - - case NT_DOMAIN_LOCAL: - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_DOMAIN_KEY, SAMR_LOCAL_DOMAIN); + if ((domain->type != NT_DOMAIN_BUILTIN) && + (domain->type != NT_DOMAIN_LOCAL)) { + bzero(¶m->domain_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + return (MLRPC_DRC_OK); + } - bcopy(handle, ¶m->domain_handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain->type, 0); + if (id) { + bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t)); param->status = 0; - break; - - default: + } else { bzero(¶m->domain_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); } return (MLRPC_DRC_OK); @@ -373,13 +407,38 @@ static int samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryDomainInfo *param = arg; - ms_handle_desc_t *desc; - char *hostname; - char *domain_str = ""; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + char *domain; + int alias_cnt; int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + + data = (samr_keydata_t *)hd->nh_data; + + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + domain = "Builtin"; + break; + + case NT_DOMAIN_LOCAL: + domain = MLRPC_HEAP_MALLOC(mxa, MAXHOSTNAMELEN); + rc = smb_gethostname(domain, MAXHOSTNAMELEN, 1); + + if (rc != 0 || domain == NULL) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + return (MLRPC_DRC_OK); + } + break; + + default: bzero(param, sizeof (struct samr_QueryDomainInfo)); param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); @@ -401,21 +460,13 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) break; case SAMR_QUERY_DOMAIN_INFO_2: - if (desc->discrim == SAMR_LOCAL_DOMAIN) { - hostname = MLRPC_HEAP_MALLOC(mxa, MAXHOSTNAMELEN); - rc = smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - if (rc != 0 || hostname == NULL) { - bzero(param, - sizeof (struct samr_QueryDomainInfo)); - param->status = - NT_SC_ERROR(NT_STATUS_NO_MEMORY); - return (MLRPC_DRC_OK); - } - - domain_str = hostname; - } else { - if (desc->discrim == SAMR_BUILTIN_DOMAIN) - domain_str = "Builtin"; + rc = (data->kd_type == NT_DOMAIN_BUILTIN) + ? smb_lgrp_numbydomain(SMB_LGRP_BUILTIN, &alias_cnt) + : smb_lgrp_numbydomain(SMB_LGRP_LOCAL, &alias_cnt); + if (rc != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_QueryDomainInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); + return (MLRPC_DRC_OK); } param->ru.info2.unknown1 = 0x00000000; @@ -425,7 +476,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) "", mxa); (void) mlsvc_string_save( - (ms_string_t *)&(param->ru.info2.domain), domain_str, mxa); + (ms_string_t *)&(param->ru.info2.domain), domain, mxa); (void) mlsvc_string_save((ms_string_t *)&(param->ru.info2.s2), "", mxa); @@ -437,11 +488,7 @@ samr_s_QueryDomainInfo(void *arg, struct mlrpc_xaction *mxa) param->ru.info2.unknown6 = 0x00000001; param->ru.info2.num_users = 0; param->ru.info2.num_groups = 0; - param->ru.info2.num_aliases = - (desc->discrim == SAMR_BUILTIN_DOMAIN) ? - nt_groups_count(NT_GROUP_CNT_BUILTIN) : - nt_groups_count(NT_GROUP_CNT_LOCAL); - + param->ru.info2.num_aliases = alias_cnt; param->status = NT_STATUS_SUCCESS; break; @@ -466,83 +513,85 @@ static int samr_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) { struct samr_LookupNames *param = arg; - ms_handle_desc_t *desc; - struct passwd *pw; - struct group *gr; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; + well_known_account_t *wka; + smb_group_t grp; + smb_passwd_t smbpw; nt_sid_t *sid; - nt_group_t *grp; - WORD rid_type; + uint32_t status = NT_STATUS_SUCCESS; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->handle); - if (desc == 0 || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - bzero(param, sizeof (struct samr_LookupNames)); - param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - return (MLRPC_DRC_OK); - } + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) + status = NT_STATUS_INVALID_HANDLE; - if (param->n_entry != 1) { - bzero(param, sizeof (struct samr_LookupNames)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } + if (param->n_entry != 1) + status = NT_STATUS_ACCESS_DENIED; if (param->name.str == NULL) { - bzero(param, sizeof (struct samr_LookupNames)); /* - * Windows NT returns NT_STATUS_NONE_MAPPED when the - * name is NULL. + * Windows NT returns NT_STATUS_NONE_MAPPED. * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME. */ - param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED); + status = NT_STATUS_NONE_MAPPED; + } + + if (status != NT_STATUS_SUCCESS) { + bzero(param, sizeof (struct samr_LookupNames)); + param->status = NT_SC_ERROR(status); return (MLRPC_DRC_OK); } param->rids.rid = MLRPC_HEAP_NEW(mxa, DWORD); param->rid_types.rid_type = MLRPC_HEAP_NEW(mxa, DWORD); - if (desc->discrim == SAMR_BUILTIN_DOMAIN) { - sid = nt_builtin_lookup_name((char *)param->name.str, - &rid_type); + data = (samr_keydata_t *)hd->nh_data; - if (sid != 0) { + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + wka = nt_builtin_lookup((char *)param->name.str); + if (wka != NULL) { param->rids.n_entry = 1; - (void) nt_sid_get_rid(sid, ¶m->rids.rid[0]); + (void) nt_sid_get_rid(wka->binsid, ¶m->rids.rid[0]); param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = rid_type; + param->rid_types.rid_type[0] = wka->sid_name_use; param->status = NT_STATUS_SUCCESS; - free(sid); return (MLRPC_DRC_OK); } - } else if (desc->discrim == SAMR_LOCAL_DOMAIN) { - grp = nt_group_getinfo((char *)param->name.str, RWLOCK_READER); + break; - if (grp != NULL) { + case NT_DOMAIN_LOCAL: + rc = smb_lgrp_getbyname((char *)param->name.str, &grp); + if (rc == SMB_LGRP_SUCCESS) { param->rids.n_entry = 1; - (void) nt_sid_get_rid(grp->sid, ¶m->rids.rid[0]); + param->rids.rid[0] = grp.sg_rid; param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = *grp->sid_name_use; + param->rid_types.rid_type[0] = grp.sg_id.gs_type; param->status = NT_STATUS_SUCCESS; - nt_group_putinfo(grp); + smb_lgrp_free(&grp); return (MLRPC_DRC_OK); } - if ((pw = getpwnam((const char *)param->name.str)) != NULL) { - param->rids.n_entry = 1; - param->rids.rid[0] = SAM_ENCODE_UXUID(pw->pw_uid); - param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = SidTypeUser; - param->status = NT_STATUS_SUCCESS; - return (MLRPC_DRC_OK); + if (smb_pwd_getpasswd((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) nt_sid_get_rid(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 (MLRPC_DRC_OK); + } } + break; - if ((gr = getgrnam((const char *)param->name.str)) != NULL) { - param->rids.n_entry = 1; - param->rids.rid[0] = SAM_ENCODE_UXGID(gr->gr_gid); - param->rid_types.n_entry = 1; - param->rid_types.rid_type[0] = SidTypeAlias; - param->status = NT_STATUS_SUCCESS; - return (MLRPC_DRC_OK); - } + default: + bzero(param, sizeof (struct samr_LookupNames)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); } param->rids.n_entry = 0; @@ -559,38 +608,44 @@ samr_s_LookupNames(void *arg, struct mlrpc_xaction *mxa) * obtained via a successful domain open request. The user is * specified by the rid in the request. */ -/*ARGSUSED*/ static int samr_s_OpenUser(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenUser *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_DOMAIN_KEY)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { bzero(¶m->user_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_USER_KEY, - param->rid); - bcopy(handle, ¶m->user_handle, sizeof (samr_handle_t)); + data = (samr_keydata_t *)hd->nh_data; + + id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid); + if (id == NULL) { + bzero(¶m->user_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } else { + bcopy(id, ¶m->user_handle, sizeof (samr_handle_t)); + /* + * Need QueryUserInfo(level 21). + */ + samr_hdfree(mxa, id); + bzero(¶m->user_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + } - /* - * Need QueryUserInfo(level 21). - */ - bzero(¶m->user_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_DeleteUser * - * This is a request to delete a user within a specified domain in the - * local SAM database. The caller should supply a valid user handle but - * we deny access regardless. + * Request to delete a user within a specified domain in the local + * SAM database. The caller should supply a valid user handle. */ /*ARGSUSED*/ static int @@ -598,6 +653,7 @@ samr_s_DeleteUser(void *arg, struct mlrpc_xaction *mxa) { struct samr_DeleteUser *param = arg; + bzero(param, sizeof (struct samr_DeleteUser)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } @@ -605,6 +661,8 @@ samr_s_DeleteUser(void *arg, struct mlrpc_xaction *mxa) /* * samr_s_QueryUserInfo * + * The caller should provide a valid user key. + * * Returns: * NT_STATUS_SUCCESS * NT_STATUS_ACCESS_DENIED @@ -616,60 +674,108 @@ samr_s_QueryUserInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryUserInfo *param = arg; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->user_handle, SAMR_USER_KEY)) { - bzero(param, sizeof (struct samr_QueryUserInfo)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); - } - bzero(param, sizeof (struct samr_QueryUserInfo)); - param->status = 0; + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_QueryUserGroups * - * This is a request to obtain a list of groups of which a user is a - * member. The user is identified from the handle, which contains an - * encoded uid in the discriminator field. - * - * Get complete list of groups and check for builtin domain. + * Request the list of groups of which a user is a member. + * The user is identified from the handle, which contains an + * rid in the discriminator field. Note that this is a local user. */ static int samr_s_QueryUserGroups(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryUserGroups *param = arg; struct samr_UserGroupInfo *info; - ms_handle_desc_t *desc; - struct passwd *pw; - DWORD uid; + struct samr_UserGroups *group; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + well_known_account_t *wka; + nt_sid_t *user_sid = NULL; + nt_sid_t *dom_sid; + smb_group_t grp; + smb_giter_t gi; + uint32_t status; + int size; + int ngrp_max; + + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) { + status = NT_STATUS_ACCESS_DENIED; + goto query_error; + } - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->user_handle); - if (desc == 0 || strcmp(desc->key, SAMR_USER_KEY)) { - bzero(param, sizeof (struct samr_QueryUserGroups)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); + data = (samr_keydata_t *)hd->nh_data; + switch (data->kd_type) { + case NT_DOMAIN_BUILTIN: + wka = nt_builtin_lookup("builtin"); + if (wka == NULL) { + status = NT_STATUS_INTERNAL_ERROR; + goto query_error; + } + dom_sid = wka->binsid; + break; + case NT_DOMAIN_LOCAL: + dom_sid = nt_domain_local_sid(); + break; + default: + status = NT_STATUS_INVALID_HANDLE; + goto query_error; + } + + user_sid = nt_sid_splice(dom_sid, data->kd_rid); + if (user_sid == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; } info = MLRPC_HEAP_NEW(mxa, struct samr_UserGroupInfo); - info->groups = MLRPC_HEAP_NEW(mxa, struct samr_UserGroups); + if (info == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; + } + bzero(info, sizeof (struct samr_UserGroupInfo)); - uid = SAM_DECODE_RID(desc->discrim); + size = 32 * 1024; + info->groups = MLRPC_HEAP_MALLOC(mxa, size); + if (info->groups == NULL) { + status = NT_STATUS_NO_MEMORY; + goto query_error; + } + ngrp_max = size / sizeof (struct samr_UserGroups); - if ((pw = getpwuid(uid)) != 0) { - info->n_entry = 1; - info->groups->rid = SAM_ENCODE_UXGID(pw->pw_gid); - info->groups->attr = SE_GROUP_MANDATORY - | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED; - param->info = info; - param->status = 0; - } else { - bzero(param, sizeof (struct samr_QueryUserGroups)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + status = NT_STATUS_INTERNAL_ERROR; + goto query_error; } + info->n_entry = 0; + group = info->groups; + while ((info->n_entry < ngrp_max) && + (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) { + if (smb_lgrp_is_member(&grp, user_sid)) { + group->rid = grp.sg_rid; + group->attr = grp.sg_attr; + group++; + info->n_entry++; + } + smb_lgrp_free(&grp); + } + smb_lgrp_iterclose(&gi); + + free(user_sid); + param->info = info; + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); + +query_error: + free(user_sid); + bzero(param, sizeof (struct samr_QueryUserGroups)); + param->status = NT_SC_ERROR(status); return (MLRPC_DRC_OK); } @@ -684,50 +790,59 @@ samr_s_QueryUserGroups(void *arg, struct mlrpc_xaction *mxa) * * We return a handle to be used to access information about this group. */ -/*ARGSUSED*/ static int samr_s_OpenGroup(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenGroup *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; + ndr_handle_t *hd; + samr_keydata_t *data; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->handle, SAMR_DOMAIN_KEY)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { bzero(¶m->group_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_GROUP_KEY, - param->rid); - bcopy(handle, ¶m->group_handle, sizeof (samr_handle_t)); + data = (samr_keydata_t *)hd->nh_data; + id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid); + + if (id) { + bcopy(id, ¶m->group_handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->group_handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } /* * samr_s_Connect * - * This is a request to connect to the local SAM database. We don't - * support any form of update request and our database doesn't - * contain any private information, so there is little point in - * doing any access access checking here. + * This is a request to connect to the local SAM database. + * We don't support any form of update request and our database doesn't + * contain any private information, so there is little point in doing + * any access access checking here. * * Return a handle for use with subsequent SAM requests. */ -/*ARGSUSED*/ static int samr_s_Connect(void *arg, struct mlrpc_xaction *mxa) { struct samr_Connect *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, - SAMR_CONNECT_KEY, SAMR_DATABASE_DOMAIN); - bcopy(handle, ¶m->handle, sizeof (samr_handle_t)); + id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, NT_DOMAIN_NULL, 0); + if (id) { + bcopy(id, ¶m->handle, sizeof (samr_handle_t)); + param->status = 0; + } else { + bzero(¶m->handle, sizeof (samr_handle_t)); + param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY); + } - param->status = 0; return (MLRPC_DRC_OK); } @@ -741,24 +856,14 @@ static int samr_s_GetUserPwInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_GetUserPwInfo *param = arg; - ms_handle_t *handle; - DWORD status = 0; - - handle = (ms_handle_t *)¶m->user_handle; - - if (!mlsvc_validate_handle(handle, SAMR_USER_KEY)) - status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); bzero(param, sizeof (struct samr_GetUserPwInfo)); - param->status = status; + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); } /* * samr_s_CreateUser - * - * This is a request to create a user within a specified domain in the - * local SAM database. We always deny access. */ /*ARGSUSED*/ static int @@ -816,25 +921,25 @@ samr_s_SetUserInfo(void *arg, struct mlrpc_xaction *mxa) /* * samr_s_QueryDispInfo * - * This function is supposed to return local users' information. + * This function is supposed to return local user information. * As we don't support local users, this function dosen't send * back any information. * - * I added a peice of code that returns information for Administrator - * and Guest builtin users. All information are hard-coded which I get - * from packet captures. Currently, this peice of code is opt-out. + * Added template that returns information for Administrator and Guest + * builtin users. All information is hard-coded from packet captures. */ -/*ARGSUSED*/ static int samr_s_QueryDispInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryDispInfo *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; DWORD status = 0; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) - status = NT_STATUS_INVALID_HANDLE; + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { + bzero(param, sizeof (struct samr_QueryDispInfo)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } #ifdef SAMR_SUPPORT_USER if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) { @@ -897,24 +1002,21 @@ samr_s_QueryDispInfo(void *arg, struct mlrpc_xaction *mxa) * samr_s_EnumDomainGroups * * - * This function is supposed to return local users' information. + * This function is supposed to return local group information. * As we don't support local users, this function dosen't send * back any information. * - * I added a peice of code that returns information for a - * domain group as None. All information are hard-coded which I get - * from packet captures. Currently, this peice of code is opt-out. + * Added template that returns information for a domain group as None. + * All information is hard-coded from packet captures. */ -/*ARGSUSED*/ static int samr_s_EnumDomainGroups(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumDomainGroups *param = arg; - ms_handle_desc_t *desc; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; DWORD status = NT_STATUS_SUCCESS; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); param->total_size = 0; @@ -964,18 +1066,17 @@ samr_s_EnumDomainGroups(void *arg, struct mlrpc_xaction *mxa) * for that alias. The alias domain sid should match with * the passed domain handle. */ -/*ARGSUSED*/ static int samr_s_OpenAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_OpenAlias *param = arg; - ms_handle_desc_t *desc = 0; - ms_handle_t *handle; - nt_group_t *grp; - DWORD status = NT_STATUS_SUCCESS; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + uint32_t status; + samr_keydata_t *data; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == 0 || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { status = NT_STATUS_INVALID_HANDLE; goto open_alias_err; } @@ -985,25 +1086,21 @@ samr_s_OpenAlias(void *arg, struct mlrpc_xaction *mxa) goto open_alias_err; } - grp = nt_groups_lookup_rid(param->rid); - if (grp == 0) { + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(param->rid, (smb_gdomain_t)data->kd_type, NULL); + if (rc != SMB_LGRP_SUCCESS) { status = NT_STATUS_NO_SUCH_ALIAS; goto open_alias_err; } - if (((desc->discrim == SAMR_LOCAL_DOMAIN) && - !nt_sid_is_local(grp->sid)) || - ((desc->discrim == SAMR_BUILTIN_DOMAIN) && - !nt_sid_is_builtin(grp->sid))) { - status = NT_STATUS_NO_SUCH_ALIAS; - goto open_alias_err; + id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid); + if (id) { + bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t)); + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SAMR, SAMR_ALIAS_KEY, - param->rid); - bcopy(handle, ¶m->alias_handle, sizeof (samr_handle_t)); - param->status = 0; - return (MLRPC_DRC_OK); + status = NT_STATUS_NO_MEMORY; open_alias_err: bzero(¶m->alias_handle, sizeof (samr_handle_t)); @@ -1025,33 +1122,29 @@ static int samr_s_CreateDomainAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_CreateDomainAlias *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + + if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL) { + bzero(param, sizeof (struct samr_CreateDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + + bzero(param, sizeof (struct samr_CreateDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); + return (MLRPC_DRC_OK); #ifdef SAMR_SUPPORT_ADD_ALIAS DWORD status = NT_STATUS_SUCCESS; - ms_handle_desc_t *desc = 0; - ms_handle_t *handle; nt_group_t *grp; char *alias_name; -#endif - bzero(¶m->alias_handle, sizeof (samr_handle_t)); - param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); - return (MLRPC_DRC_OK); -#ifdef SAMR_SUPPORT_ADD_ALIAS alias_name = param->alias_name.str; if (alias_name == 0) { status = NT_STATUS_INVALID_PARAMETER; goto create_alias_err; } - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == 0 || - (desc->discrim != SAMR_LOCAL_DOMAIN) || - (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto create_alias_err; - } - /* * Check access mask. User should be member of * Administrators or Account Operators local group. @@ -1087,19 +1180,17 @@ create_alias_err: /* * samr_s_SetAliasInfo * - * For more information you can look at MSDN page for NetLocalGroupSetInfo. + * Similar to NetLocalGroupSetInfo. */ -/*ARGSUSED*/ static int samr_s_SetAliasInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_SetAliasInfo *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; DWORD status = NT_STATUS_SUCCESS; - if (!mlsvc_validate_handle( - (ms_handle_t *)¶m->alias_handle, SAMR_ALIAS_KEY)) { + if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); - } param->status = status; return (MLRPC_DRC_OK); @@ -1115,18 +1206,22 @@ static int samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) { struct samr_QueryAliasInfo *param = arg; - ms_handle_desc_t *desc; - nt_group_t *grp; - DWORD status; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + uint32_t status; + int rc; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->alias_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_ALIAS_KEY) != 0)) { + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) { status = NT_STATUS_INVALID_HANDLE; goto query_alias_err; } - grp = nt_groups_lookup_rid(desc->discrim); - if (grp == NULL) { + data = (samr_keydata_t *)hd->nh_data; + rc = smb_lgrp_getbyrid(data->kd_rid, (smb_gdomain_t)data->kd_type, + &grp); + if (rc != SMB_LGRP_SUCCESS) { status = NT_STATUS_NO_SUCH_ALIAS; goto query_alias_err; } @@ -1135,10 +1230,10 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) case SAMR_QUERY_ALIAS_INFO_1: param->ru.info1.level = param->level; (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info1.name, grp->name, mxa); + (ms_string_t *)¶m->ru.info1.name, grp.sg_name, mxa); (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info1.desc, grp->comment, mxa); + (ms_string_t *)¶m->ru.info1.desc, grp.sg_cmnt, mxa); param->ru.info1.unknown = 1; break; @@ -1146,15 +1241,16 @@ samr_s_QueryAliasInfo(void *arg, struct mlrpc_xaction *mxa) case SAMR_QUERY_ALIAS_INFO_3: param->ru.info3.level = param->level; (void) mlsvc_string_save( - (ms_string_t *)¶m->ru.info3.desc, grp->comment, mxa); - + (ms_string_t *)¶m->ru.info3.desc, grp.sg_cmnt, mxa); break; default: + smb_lgrp_free(&grp); status = NT_STATUS_INVALID_INFO_CLASS; goto query_alias_err; }; + smb_lgrp_free(&grp); param->address = (DWORD)(uintptr_t)¶m->ru; param->status = 0; return (MLRPC_DRC_OK); @@ -1176,28 +1272,26 @@ query_alias_err: * This RPC is used by CMC and right now it returns access denied. * The peice of code that removes a local group doesn't get compiled. */ -/*ARGSUSED*/ static int samr_s_DeleteDomainAlias(void *arg, struct mlrpc_xaction *mxa) { struct samr_DeleteDomainAlias *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle; -#ifdef SAMR_SUPPORT_DEL_ALIAS - ms_handle_desc_t *desc = 0; - nt_group_t *grp; - char *alias_name; - DWORD status; -#endif + if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL) { + bzero(param, sizeof (struct samr_DeleteDomainAlias)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); + } + bzero(param, sizeof (struct samr_DeleteDomainAlias)); param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED); return (MLRPC_DRC_OK); #ifdef SAMR_SUPPORT_DEL_ALIAS - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->alias_handle); - if (desc == 0 || (strcmp(desc->key, SAMR_ALIAS_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto delete_alias_err; - } + nt_group_t *grp; + char *alias_name; + DWORD status; grp = nt_groups_lookup_rid(desc->discrim); if (grp == 0) { @@ -1234,77 +1328,65 @@ static int samr_s_EnumDomainAliases(void *arg, struct mlrpc_xaction *mxa) { struct samr_EnumDomainAliases *param = arg; - ms_handle_desc_t *desc; - nt_group_t *grp = NULL; - DWORD status; - nt_group_iterator_t *gi; - nt_sid_t *local_sid; - nt_sid_t *builtin_sid; - nt_sid_t *sid; - DWORD cnt, skip; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle; + ndr_handle_t *hd; + samr_keydata_t *data; + smb_group_t grp; + smb_giter_t gi; + int cnt, skip, i; struct name_rid *info; - desc = mlsvc_lookup_handle((ms_handle_t *)¶m->domain_handle); - if (desc == NULL || (strcmp(desc->key, SAMR_DOMAIN_KEY) != 0)) { - status = NT_STATUS_INVALID_HANDLE; - goto enum_alias_err; + if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) { + bzero(param, sizeof (struct samr_EnumDomainAliases)); + param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE); + return (MLRPC_DRC_OK); } - local_sid = nt_domain_local_sid(); - builtin_sid = nt_builtin_lookup_name("BUILTIN", 0); + data = (samr_keydata_t *)hd->nh_data; - if (desc->discrim == SAMR_LOCAL_DOMAIN) { - sid = local_sid; - } else if (desc->discrim == SAMR_BUILTIN_DOMAIN) { - sid = builtin_sid; - } else { - status = NT_STATUS_INVALID_HANDLE; - goto enum_alias_err; - } + (void) smb_lgrp_numbydomain((smb_gdomain_t)data->kd_type, &cnt); + if (cnt <= param->resume_handle) { + param->aliases = (struct aliases_info *)MLRPC_HEAP_MALLOC(mxa, + sizeof (struct aliases_info)); - cnt = skip = 0; - gi = nt_group_open_iterator(); - nt_group_ht_lock(RWLOCK_READER); - while ((grp = nt_group_iterate(gi)) != 0) { - if (skip++ < param->resume_handle) - continue; - if (nt_sid_is_indomain(sid, grp->sid)) - cnt++; + bzero(param->aliases, sizeof (struct aliases_info)); + param->out_resume = 0; + param->entries = 0; + param->status = NT_STATUS_SUCCESS; + return (MLRPC_DRC_OK); } - nt_group_ht_unlock(); - nt_group_close_iterator(gi); + cnt -= param->resume_handle; param->aliases = (struct aliases_info *)MLRPC_HEAP_MALLOC(mxa, sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid)); - param->aliases->count = cnt; - param->aliases->address = cnt; - info = param->aliases->info; + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + bzero(param, sizeof (struct samr_EnumDomainAliases)); + param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR); + return (MLRPC_DRC_OK); + } - skip = 0; - gi = nt_group_open_iterator(); - nt_group_ht_lock(RWLOCK_READER); - while ((grp = nt_group_iterate(gi)) != NULL) { - if (skip++ < param->resume_handle) - continue; - if (nt_sid_is_indomain(sid, grp->sid)) { - (void) nt_sid_get_rid(grp->sid, &info->rid); + skip = i = 0; + info = param->aliases->info; + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + if ((skip++ >= param->resume_handle) && + (grp.sg_domain == data->kd_type) && (i++ < cnt)) { + info->rid = grp.sg_rid; (void) mlsvc_string_save((ms_string_t *)&info->name, - grp->name, mxa); + grp.sg_name, mxa); info++; } + smb_lgrp_free(&grp); } - nt_group_ht_unlock(); - nt_group_close_iterator(gi); + smb_lgrp_iterclose(&gi); - param->out_resume = cnt; - param->entries = cnt; - param->status = 0; - return (MLRPC_DRC_OK); + param->aliases->count = i; + param->aliases->address = i; -enum_alias_err: - param->status = NT_SC_ERROR(status); + param->out_resume = i; + param->entries = i; + param->status = 0; return (MLRPC_DRC_OK); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c index 26cd32ac5d..fbb37f5d04 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_srvsvc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -100,21 +100,6 @@ static mlrpc_service_t srvsvc_service = { }; /* - * srvsvc_fix_comment - * - * The parser sometimes has problems with empty strings so we - * need to ensure that the comment field has something in it. - */ -static inline char * -srvsvc_fix_comment(char *original, char *alternative) -{ - if (original == 0 || strlen(original) == 0) - return (alternative); - - return (original); -} - -/* * srvsvc_share_mkpath * * Create the share path required by the share enum calls. This function @@ -516,12 +501,10 @@ srvsvc_s_NetShareSetInfo(void *arg, struct mlrpc_xaction *mxa) sizeof (DWORD)); param->parm_err = 0; - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_SRVSVC_SHRSET_ENABLE) != 0) + if (!smb_config_getbool(SMB_CI_SRVSVC_SHRSET_ENABLE)) param->status = ERROR_SUCCESS; else param->status = ERROR_ACCESS_DENIED; - smb_config_unlock(); return (MLRPC_DRC_OK); } @@ -805,7 +788,7 @@ srvsvc_s_NetServerGetInfo(void *arg, struct mlrpc_xaction *mxa) struct mslm_SERVER_INFO_100 *info100; struct mslm_SERVER_INFO_101 *info101; struct mslm_SERVER_INFO_102 *info102; - char *sys_comment; + char sys_comment[SMB_PI_MAX_COMMENT]; char hostname[MAXHOSTNAMELEN]; if (smb_gethostname(hostname, MAXHOSTNAMELEN, 1) != 0) { @@ -814,10 +797,10 @@ netservergetinfo_no_memory: return (ERROR_NOT_ENOUGH_MEMORY); } - smb_config_rdlock(); - sys_comment = smb_config_getstr(SMB_CI_SYS_CMNT); - sys_comment = srvsvc_fix_comment(sys_comment, " "); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, sys_comment, + sizeof (sys_comment)); + if (*sys_comment == '\0') + (void) strcpy(sys_comment, " "); switch (param->level) { case 100: diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c index eca831f899..242fdbc75f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_svcctl.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,17 +43,10 @@ #include <smbsrv/ndl/svcctl.ndl> /* - * SVCCTL diagnostics flag: set to 1 to enable verbose logging. + * The handle keys for this interface. */ -int svcctl_debug = 0; - -/* - * The handle keys for the various types of handles returned - * by this interface. - */ -#define SVCCTL_MANAGER_KEY "svcctlManager" -#define SVCCTL_SERVICE_KEY "svcctlService" - +static int svcctl_key_manager; +static int svcctl_key_service; typedef struct { char *svc_name; @@ -93,8 +86,6 @@ static svc_info_t svc_info[] = { static DWORD svcctl_get_status(const char *); static DWORD svcctl_validate_service(char *); -static DWORD svcctl_validate_handle(char *, ms_handle_t *, char *, - struct mlrpc_xaction *); static int svcctl_is_admin(struct mlrpc_xaction *); static int svcctl_s_Close(void *, struct mlrpc_xaction *); @@ -157,60 +148,51 @@ static int svcctl_s_Close(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_Close *param = arg; - smb_dr_user_ctx_t *user_ctx = mxa->context->user_ctx; - ms_handle_t *handle; - DWORD status; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - if (svcctl_debug) - smb_token_log(LOG_DEBUG, user_ctx, "(SvcctlClose)"); - - handle = (ms_handle_t *)¶m->handle; - status = svcctl_validate_handle("SvcctlClose", handle, 0, mxa); - - if (status == ERROR_SUCCESS) - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); + ndr_hdfree(mxa, id); bzero(¶m->result_handle, sizeof (svcctl_handle_t)); - param->status = status; + param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } /* * svcctl_s_OpenManager * - * This is a request to open the service control manager. Dependent - * on the desired access we either generate a handle to be used on - * subsequent requests or deny access. + * Request to open the service control manager. + * The caller must have administrator rights in order to open this + * interface. We don't support write access. * * Returns: * ERROR_SUCCESS * ERROR_ACCESS_DENIED * - * Return a handle for use with subsequent svcctl requests. + * On success, returns a handle for use with subsequent svcctl requests. */ static int svcctl_s_OpenManager(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_OpenManager *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id; int rc; rc = svcctl_is_admin(mxa); if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) { - /* - * The user doesn't have Administrator rights - * or wants a write lock on the Services DB. - */ bzero(¶m->handle, sizeof (svcctl_handle_t)); param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SVCCTL, SVCCTL_MANAGER_KEY, 0); - bcopy(handle, ¶m->handle, sizeof (svcctl_handle_t)); + if ((id = ndr_hdalloc(mxa, &svcctl_key_manager)) != NULL) { + bcopy(id, ¶m->handle, sizeof (svcctl_handle_t)); + param->status = ERROR_SUCCESS; + } else { + bzero(¶m->handle, sizeof (svcctl_handle_t)); + param->status = ERROR_ACCESS_DENIED; + } - param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -228,15 +210,14 @@ static int svcctl_s_OpenService(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_OpenService *param = arg; - ms_handle_t *handle; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; + ndr_handle_t *hd; DWORD status; - status = svcctl_validate_handle("SvcctlOpenService", - (ms_handle_t *)¶m->manager_handle, SVCCTL_MANAGER_KEY, mxa); - - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_manager)) { bzero(¶m->service_handle, sizeof (svcctl_handle_t)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -247,10 +228,14 @@ svcctl_s_OpenService(void *arg, struct mlrpc_xaction *mxa) return (MLRPC_DRC_OK); } - handle = mlsvc_get_handle(MLSVC_IFSPEC_SVCCTL, SVCCTL_SERVICE_KEY, 0); - bcopy(handle, ¶m->service_handle, sizeof (svcctl_handle_t)); + if ((id = ndr_hdalloc(mxa, &svcctl_key_service)) != NULL) { + bcopy(id, ¶m->service_handle, sizeof (svcctl_handle_t)); + param->status = ERROR_SUCCESS; + } else { + bzero(¶m->service_handle, sizeof (svcctl_handle_t)); + param->status = ERROR_ACCESS_DENIED; + } - param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -265,14 +250,13 @@ static int svcctl_s_QueryServiceStatus(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_QueryServiceStatus *param = arg; - DWORD status; - - status = svcctl_validate_handle("SvcctlQueryServiceStatus", - (ms_handle_t *)¶m->service_handle, SVCCTL_SERVICE_KEY, mxa); + ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; + ndr_handle_t *hd; - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { bzero(¶m, sizeof (struct svcctl_QueryServiceStatus)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -303,19 +287,19 @@ static int svcctl_s_EnumServicesStatus(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_EnumServicesStatus *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; + ndr_handle_t *hd; svc_enum_status_t *service_table; svc_enum_status_t *svc; mts_wchar_t *wide_name; char *name; int i, namelen; int offs; - DWORD status; - status = svcctl_validate_handle("SvcctlEnumServicesStatus", - (ms_handle_t *)¶m->manager_handle, SVCCTL_MANAGER_KEY, mxa); - - if (status != ERROR_SUCCESS) { - param->status = status; + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_manager)) { + bzero(¶m, sizeof (struct svcctl_EnumServicesStatus)); + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -382,14 +366,13 @@ static int svcctl_s_QueryServiceConfig(void *arg, struct mlrpc_xaction *mxa) { struct svcctl_QueryServiceConfig *param = arg; - DWORD status; - - status = svcctl_validate_handle("SvcctlQueryServiceConfig", - (ms_handle_t *)¶m->service_handle, SVCCTL_SERVICE_KEY, mxa); + ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; + ndr_handle_t *hd; - if (status != ERROR_SUCCESS) { + hd = ndr_hdlookup(mxa, id); + if ((hd == NULL) || (hd->nh_data != &svcctl_key_service)) { bzero(¶m, sizeof (struct svcctl_QueryServiceConfig)); - param->status = status; + param->status = ERROR_INVALID_HANDLE; return (MLRPC_DRC_OK); } @@ -434,30 +417,6 @@ svcctl_validate_service(char *svc_name) } /* - * Check whether or not the svcctl module allocated this handle. - * - * Returns: - * ERROR_SUCCESS - * ERROR_INVALID_HANDLE. - */ -/*ARGSUSED*/ -static DWORD -svcctl_validate_handle(char *name, ms_handle_t *handle, char *key, - struct mlrpc_xaction *mxa) -{ - int mgr_erc; - int svc_erc; - - mgr_erc = mlsvc_validate_handle(handle, SVCCTL_MANAGER_KEY); - svc_erc = mlsvc_validate_handle(handle, SVCCTL_SERVICE_KEY); - - if (mgr_erc == 0 && svc_erc == 0) - return (ERROR_INVALID_HANDLE); - - return (ERROR_SUCCESS); -} - -/* * Report the service status: SERVICE_PAUSED or SERVICE_RUNNING. */ /*ARGSUSED*/ diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c index 81e3893781..94f50d40b4 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,8 +35,6 @@ #include <unistd.h> #include <netdb.h> #include <stdlib.h> -#include <pwd.h> -#include <grp.h> #include <sys/time.h> #include <sys/systm.h> @@ -53,15 +51,14 @@ #include <smbsrv/mlsvc_util.h> #include <smbsrv/mlsvc.h> +/* Domain join support (using MS-RPC) */ +static boolean_t mlsvc_ntjoin_support = B_FALSE; + extern int netr_open(char *, char *, mlsvc_handle_t *); extern int netr_close(mlsvc_handle_t *); extern DWORD netlogon_auth(char *, mlsvc_handle_t *, DWORD); extern int mlsvc_user_getauth(char *, char *, smb_auth_info_t *); -static int mlsvc_lookup_local_name(char *name, nt_sid_t **sid); -static int mlsvc_lookup_nt_name(char *name, nt_sid_t **sid); -static int mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize); - /* * Compare the supplied domain name with the local hostname. * We need to deal with both server names and fully-qualified @@ -77,9 +74,11 @@ int mlsvc_is_local_domain(const char *domain) { char hostname[MAXHOSTNAMELEN]; - uint32_t mode; int rc; + if (smb_config_get_secmode() == SMB_SECMODE_WORKGRP) + return (1); + if (strchr(domain, '.') != NULL) rc = smb_getfqhostname(hostname, MAXHOSTNAMELEN); else @@ -88,10 +87,7 @@ mlsvc_is_local_domain(const char *domain) if (rc != 0) return (-1); - rc = strcasecmp(domain, hostname); - mode = smb_get_security_mode(); - - if ((rc == 0) || (mode == SMB_SECMODE_WORKGRP)) + if (strcasecmp(domain, hostname) == 0) return (1); return (0); @@ -100,163 +96,62 @@ mlsvc_is_local_domain(const char *domain) /* * mlsvc_lookup_name * - * Lookup a name in the specified domain and translate it to a SID. - * If the name is in the NT domain, it may refer to a user, group or - * alias. Otherwise it must refer to a UNIX username. The memory for - * the sid is allocated using malloc so the caller should call free - * when it is no longer required. - * - * On success, 0 will be returned and sid will point to a local domain - * user SID. Otherwise -1 will be returned. - */ -int -mlsvc_lookup_name(char *domain, char *name, nt_sid_t **sid) -{ - if (domain == NULL || name == NULL || sid == NULL) - return (-1); - - if (mlsvc_is_local_domain(domain) == 1) - return (mlsvc_lookup_local_name(name, sid)); - else - return (mlsvc_lookup_nt_name(name, sid)); -} - -/* - * mlsvc_lookup_local_name - * - * Lookup a name in the local password file and translate it to a SID. - * The name must refer to a user. This is a private function intended - * to support mlsvc_lookup_name so it doesn't perform any parameter - * validation. The memory for the sid is allocated using malloc so the - * caller must call free when it is no longer required. - * - * On success, 0 will be returned and sid will point to a local domain - * user SID. Otherwise -1 will be returned. - */ -static int -mlsvc_lookup_local_name(char *name, nt_sid_t **sid) -{ - struct passwd *pw; - nt_sid_t *domain_sid; - - if ((pw = getpwnam(name)) == NULL) - return (-1); - - if ((domain_sid = nt_domain_local_sid()) == NULL) - return (-1); - - *sid = nt_sid_splice(domain_sid, pw->pw_uid); - return (0); -} - -/* - * mlsvc_lookup_nt_name - * - * Lookup a name in the specified NT domain and translate it to a SID. - * The name may refer to a user, group or alias. This is a private - * function intended to support mlsvc_lookup_name so it doesn't do any - * parameter validation. The memory for the sid is allocated using - * malloc so the caller should call free when it is no longer required. + * This is just a wrapper for lsa_lookup_name. * - * On success, 0 will be returned and sid will point to an NT domain - * user SID. Otherwise -1 will be returned. + * The memory for the sid is allocated using malloc so the caller should + * call free when it is no longer required. */ -static int -mlsvc_lookup_nt_name(char *name, nt_sid_t **sid) +uint32_t +mlsvc_lookup_name(char *account, nt_sid_t **sid, uint16_t *sid_type) { - smb_userinfo_t *user_info; + smb_userinfo_t *ainfo; + uint32_t status; - if ((user_info = mlsvc_alloc_user_info()) == NULL) - return (-1); + if ((ainfo = mlsvc_alloc_user_info()) == NULL) + return (NT_STATUS_NO_MEMORY); - if (lsa_lookup_name(0, 0, name, user_info) != 0) - return (-1); + status = lsa_lookup_name(NULL, account, *sid_type, ainfo); + if (status == NT_STATUS_SUCCESS) { + *sid = ainfo->user_sid; + ainfo->user_sid = NULL; + *sid_type = ainfo->sid_name_use; + } - *sid = nt_sid_splice(user_info->domain_sid, user_info->rid); - mlsvc_free_user_info(user_info); - return (0); + mlsvc_free_user_info(ainfo); + return (status); } /* * mlsvc_lookup_sid * - * Lookup a SID and translate it to a name. The name returned may refer - * to a domain, user, group or alias dependent on the SID. On success 0 - * will be returned. Otherwise -1 will be returned. + * This is just a wrapper for lsa_lookup_sid. + * + * The allocated memory for the returned name must be freed by caller upon + * successful return. */ -int -mlsvc_lookup_sid(nt_sid_t *sid, char *buf, int bufsize) +uint32_t +mlsvc_lookup_sid(nt_sid_t *sid, char **name) { - struct passwd *pw; - struct group *gr; - nt_group_t *grp; - DWORD rid; - - if (sid == NULL || buf == NULL) - return (-1); - - if (nt_sid_is_local(sid)) { - (void) nt_sid_get_rid(sid, &rid); - - switch (SAM_RID_TYPE(rid)) { - case SAM_RT_NT_UID: - break; - - case SAM_RT_NT_GID: - if ((grp = nt_groups_lookup_rid(rid)) == NULL) - return (-1); - - (void) strlcpy(buf, grp->name, bufsize); - break; - - case SAM_RT_UNIX_UID: - if ((pw = getpwuid(SAM_DECODE_RID(rid))) == NULL) - return (-1); + smb_userinfo_t *ainfo; + uint32_t status; + int namelen; - (void) strlcpy(buf, pw->pw_name, bufsize); - break; + if ((ainfo = mlsvc_alloc_user_info()) == NULL) + return (NT_STATUS_NO_MEMORY); - case SAM_RT_UNIX_GID: - if ((gr = getgrgid(SAM_DECODE_RID(rid))) == NULL) - return (-1); - - (void) strlcpy(buf, gr->gr_name, bufsize); - break; + 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); } - - return (0); + (void) snprintf(*name, namelen, "%s\\%s", + ainfo->domain_name, ainfo->name); } - return (mlsvc_lookup_nt_sid(sid, buf, bufsize)); -} - -/* - * mlsvc_lookup_nt_sid - * - * Lookup an NT SID and translate it to a name. This is a private - * function intended to support mlsvc_lookup_sid so it doesn't do any - * parameter validation. The input account_name specifies the logon/ - * session to be used for the lookup. It doesn't need to have any - * association with the SID being looked up. The name returned may - * refer to a domain, user, group or alias dependent on the SID. - * - * On success the name will be copied into buf and 0 will be returned. - * Otherwise -1 will be returned. - */ -static int -mlsvc_lookup_nt_sid(nt_sid_t *sid, char *buf, int bufsize) -{ - smb_userinfo_t *user_info; - int rc; - - if ((user_info = mlsvc_alloc_user_info()) == NULL) - return (-1); - - if ((rc = lsa_lookup_sid(sid, user_info)) == 0) - (void) strlcpy(buf, user_info->name, bufsize); - - mlsvc_free_user_info(user_info); - return (rc); + mlsvc_free_user_info(ainfo); + return (status); } /* @@ -337,8 +232,8 @@ void mlsvc_setadmin_user_info(smb_userinfo_t *user_info) { nt_domain_t *domain; - nt_group_t *grp; - int i; + smb_group_t grp; + int rc, i; if ((domain = nt_domain_lookupbytype(NT_DOMAIN_PRIMARY)) == NULL) return; @@ -356,12 +251,11 @@ mlsvc_setadmin_user_info(smb_userinfo_t *user_info) user_info->flags |= SMB_UINFO_FLAG_DADMIN; } - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - i = nt_group_is_member(grp, user_info->user_sid); - nt_group_putinfo(grp); - if (i) + 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); } } @@ -447,6 +341,7 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) DWORD status; mlsvc_handle_t netr_handle; char machine_passwd[MLSVC_MACHINE_ACCT_PASSWD_MAX]; + char fqdn[MAXHOSTNAMELEN]; machine_passwd[0] = '\0'; @@ -472,14 +367,13 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) erc = mlsvc_logon(server, domain, plain_user); if (erc == AUTH_USER_GRANT) { - int isenabled; - - smb_config_rdlock(); - isenabled = smb_config_getyorn(SMB_CI_ADS_ENABLE); - smb_config_unlock(); - if (isenabled) { - if (ads_join(plain_user, plain_text, machine_passwd, - sizeof (machine_passwd)) == ADJOIN_SUCCESS) + if (mlsvc_ntjoin_support == B_FALSE) { + if (smb_resolve_fqdn(domain, fqdn, MAXHOSTNAMELEN) != 1) + return (NT_STATUS_INVALID_PARAMETER); + + if (ads_join(fqdn, plain_user, plain_text, + machine_passwd, sizeof (machine_passwd)) + == ADJOIN_SUCCESS) status = NT_STATUS_SUCCESS; else status = NT_STATUS_UNSUCCESSFUL; @@ -500,7 +394,9 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) } if (status == NT_STATUS_SUCCESS) { - if (smb_set_machine_pwd(machine_passwd) != 0) + erc = smb_config_setstr(SMB_CI_MACHINE_PASSWD, + machine_passwd); + if (erc != SMBD_SMF_OK) return (NT_STATUS_UNSUCCESSFUL); /* @@ -509,7 +405,7 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) * that we use the SAMLOGON version of the NETLOGON * PDC location protocol. */ - smb_set_domain_member(1); + (void) smb_config_setbool(SMB_CI_DOMAIN_MEMB, B_TRUE); if (netr_open(server, domain, &netr_handle) == 0) { status = netlogon_auth(server, &netr_handle, @@ -525,197 +421,3 @@ mlsvc_join(char *server, char *domain, char *plain_user, char *plain_text) return (status); } - -/*ARGSUSED*/ -void -nt_group_ht_lock(krwmode_t locktype) -{ -} - -void -nt_group_ht_unlock(void) -{ -} - -int -nt_group_num_groups(void) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add(char *gname, char *comment) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_modify(char *gname, char *new_gname, char *comment) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_delete(char *gname) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -nt_group_t * -nt_group_getinfo(char *gname, krwmode_t locktype) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -nt_group_putinfo(nt_group_t *grp) -{ -} - -/*ARGSUSED*/ -int -nt_group_getpriv(nt_group_t *grp, uint32_t priv_id) -{ - return (SE_PRIVILEGE_DISABLED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_setpriv(nt_group_t *grp, uint32_t priv_id, uint32_t new_attr) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -int -nt_group_is_member(nt_group_t *grp, nt_sid_t *sid) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add_member(nt_group_t *grp, nt_sid_t *msid, uint16_t sid_name_use, - char *account) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_del_member(nt_group_t *grp, void *key, int keytype) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -int -nt_group_num_members(nt_group_t *grp) -{ - return (0); -} - -nt_group_iterator_t * -nt_group_open_iterator(void) -{ - return (NULL); -} - -/*ARGSUSED*/ -void -nt_group_close_iterator(nt_group_iterator_t *gi) -{ -} - -/*ARGSUSED*/ -nt_group_t * -nt_group_iterate(nt_group_iterator_t *gi) -{ - return (NULL); -} - -int -nt_group_cache_size(void) -{ - return (0); -} - -uint32_t -sam_init(void) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -uint32_t -nt_group_add_member_byname(char *gname, char *account) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -uint32_t -nt_group_del_member_byname(nt_group_t *grp, char *member_name) -{ - return (NT_STATUS_NOT_SUPPORTED); -} - -/*ARGSUSED*/ -void -nt_group_add_groupprivs(nt_group_t *grp, smb_privset_t *priv) -{ -} - -/*ARGSUSED*/ -uint32_t -nt_groups_member_privs(nt_sid_t *sid, smb_privset_t *priv) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -int -nt_groups_member_ngroups(nt_sid_t *sid) -{ - return (0); -} - -/*ARGSUSED*/ -uint32_t -nt_groups_member_groups(nt_sid_t *sid, smb_id_t *grps, int ngrps) -{ - return (NT_STATUS_SUCCESS); -} - -/*ARGSUSED*/ -nt_group_t * -nt_groups_lookup_rid(uint32_t rid) -{ - return (NULL); -} - -/*ARGSUSED*/ -int -nt_groups_count(int cnt_opt) -{ - return (0); -} - -/*ARGSUSED*/ -int -nt_group_member_list(int offset, nt_group_t *grp, - ntgrp_member_list_t *rmembers) -{ - return (0); -} - -/*ARGSUSED*/ -void -nt_group_list(int offset, char *pattern, ntgrp_list_t *list) -{ -} diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c index 9dd5696526..9d017b57e1 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_winreg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -45,11 +45,12 @@ #include <smbsrv/ndl/winreg.ndl> /* - * List of mlsvc handle (local handle management) keys. + * Local handle management keys. */ -#define WINREG_HKLM "WinregOpenHKLM" -#define WINREG_HKU "WinregOpenUser" -#define WINREG_KEY "WinregOpenKey" +static int winreg_hk; +static int winreg_hklm; +static int winreg_hkuser; +static int winreg_hkkey; /* * List of supported registry keys (case-insensitive). @@ -62,29 +63,41 @@ static char *winreg_keys[] = { static char *winreg_lookup_value(const char *); +static int winreg_s_OpenHK(void *, struct mlrpc_xaction *); static int winreg_s_OpenHKLM(void *, struct mlrpc_xaction *); static int winreg_s_OpenHKUsers(void *, struct mlrpc_xaction *); static int winreg_s_Close(void *, struct mlrpc_xaction *); static int winreg_s_CreateKey(void *, struct mlrpc_xaction *); static int winreg_s_DeleteKey(void *, struct mlrpc_xaction *); static int winreg_s_DeleteValue(void *, struct mlrpc_xaction *); +static int winreg_s_FlushKey(void *, struct mlrpc_xaction *); +static int winreg_s_GetKeySec(void *, struct mlrpc_xaction *); +static int winreg_s_NotifyChange(void *, struct mlrpc_xaction *); static int winreg_s_OpenKey(void *, struct mlrpc_xaction *); static int winreg_s_QueryKey(void *, struct mlrpc_xaction *); static int winreg_s_QueryValue(void *, struct mlrpc_xaction *); +static int winreg_s_SetKeySec(void *, struct mlrpc_xaction *); static int winreg_s_CreateValue(void *, struct mlrpc_xaction *); static int winreg_s_Shutdown(void *, struct mlrpc_xaction *); static int winreg_s_GetVersion(void *, struct mlrpc_xaction *); static mlrpc_stub_table_t winreg_stub_table[] = { + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCR }, + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKCU }, { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM }, + { winreg_s_OpenHK, WINREG_OPNUM_OpenHKPD }, { winreg_s_OpenHKUsers, WINREG_OPNUM_OpenHKUsers }, { winreg_s_Close, WINREG_OPNUM_Close }, { winreg_s_CreateKey, WINREG_OPNUM_CreateKey }, { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey }, { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue }, + { winreg_s_FlushKey, WINREG_OPNUM_FlushKey }, + { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec }, + { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange }, { winreg_s_OpenKey, WINREG_OPNUM_OpenKey }, { winreg_s_QueryKey, WINREG_OPNUM_QueryKey }, { winreg_s_QueryValue, WINREG_OPNUM_QueryValue }, + { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec }, { winreg_s_CreateValue, WINREG_OPNUM_CreateValue }, { winreg_s_Shutdown, WINREG_OPNUM_Shutdown }, { winreg_s_GetVersion, WINREG_OPNUM_GetVersion }, @@ -131,28 +144,48 @@ winreg_initialize(void) } /* + * winreg_s_OpenHK + * + * Stub. + */ +static int +winreg_s_OpenHK(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_OpenHKCR *param = arg; + ndr_hdid_t *id; + + 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; + } + + return (MLRPC_DRC_OK); +} + +/* * winreg_s_OpenHKLM * - * This is a request to open the HKLM and get a handle. The client - * should treat the handle as an opaque object. + * 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. */ -/*ARGSUSED*/ static int winreg_s_OpenHKLM(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenHKLM *param = arg; - ms_handle_t *handle; + struct winreg_OpenHKLM *param = arg; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, WINREG_HKLM, 0); - if (handle == NULL) { - bzero(¶m->handle, sizeof (msreg_handle_t)); + if ((id = ndr_hdalloc(mxa, &winreg_hklm)) == NULL) { + bzero(¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_ACCESS_DENIED; } else { - bcopy(handle, ¶m->handle, sizeof (msreg_handle_t)); + bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; } @@ -167,19 +200,17 @@ winreg_s_OpenHKLM(void *arg, struct mlrpc_xaction *mxa) * to support subsequent requests, but we may support enough now. It * seems okay with regedt32. */ -/*ARGSUSED*/ static int winreg_s_OpenHKUsers(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenHKUsers *param = arg; - ms_handle_t *handle; + struct winreg_OpenHKUsers *param = arg; + ndr_hdid_t *id; - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, WINREG_HKU, 0); - if (handle == NULL) { - bzero(¶m->handle, sizeof (msreg_handle_t)); + if ((id = ndr_hdalloc(mxa, &winreg_hkuser)) == NULL) { + bzero(¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_ACCESS_DENIED; } else { - bcopy(handle, ¶m->handle, sizeof (msreg_handle_t)); + bcopy(id, ¶m->handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; } @@ -194,14 +225,15 @@ winreg_s_OpenHKUsers(void *arg, struct mlrpc_xaction *mxa) * and return MLRPC_DRC_OK. Setting the handle to zero appears to be * standard behaviour. */ -/*ARGSUSED*/ static int winreg_s_Close(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_Close *param = arg; + struct winreg_Close *param = arg; + ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; - (void) mlsvc_put_handle((ms_handle_t *)¶m->handle); - bzero(¶m->result_handle, sizeof (msreg_handle_t)); + ndr_hdfree(mxa, id); + + bzero(¶m->result_handle, sizeof (winreg_handle_t)); param->status = ERROR_SUCCESS; return (MLRPC_DRC_OK); } @@ -213,7 +245,7 @@ winreg_s_Close(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_CreateKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_CreateKey *param = arg; + struct winreg_CreateKey *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -226,7 +258,7 @@ winreg_s_CreateKey(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_DeleteKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_DeleteKey *param = arg; + struct winreg_DeleteKey *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -239,13 +271,53 @@ winreg_s_DeleteKey(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_DeleteValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_DeleteValue *param = arg; + struct winreg_DeleteValue *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); } /* + * winreg_s_FlushKey + */ +/*ARGSUSED*/ +static int +winreg_s_FlushKey(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_FlushKey *param = arg; + + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* + * winreg_s_GetKeySec + */ +/*ARGSUSED*/ +static int +winreg_s_GetKeySec(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_GetKeySec *param = arg; + + bzero(param, sizeof (struct winreg_GetKeySec)); + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* + * winreg_s_NotifyChange + */ +/*ARGSUSED*/ +static int +winreg_s_NotifyChange(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_NotifyChange *param = arg; + + param->status = ERROR_SUCCESS; + return (MLRPC_DRC_OK); +} + +/* * winreg_s_OpenKey * * This is a request to open a windows registry key. The list @@ -256,33 +328,29 @@ winreg_s_DeleteValue(void *arg, struct mlrpc_xaction *mxa) * ERROR_SUCCESS Valid handle returned. * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle. */ -/*ARGSUSED*/ static int winreg_s_OpenKey(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_OpenKey *param = arg; - ms_handle_t *handle; + struct winreg_OpenKey *param = arg; char *key = (char *)param->name.str; + ndr_hdid_t *id = NULL; int i; for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i) { if (strcasecmp(key, winreg_keys[i]) == 0) { - handle = mlsvc_get_handle(MLSVC_IFSPEC_WINREG, - WINREG_KEY, 0); - - if (handle == NULL) - break; - - bcopy(handle, ¶m->result_handle, - sizeof (msreg_handle_t)); - - param->status = ERROR_SUCCESS; - return (MLRPC_DRC_OK); + id = ndr_hdalloc(mxa, &winreg_hkkey); + break; } } - bzero(¶m->result_handle, sizeof (msreg_handle_t)); - param->status = ERROR_FILE_NOT_FOUND; + if (id == NULL) { + bzero(¶m->result_handle, sizeof (winreg_handle_t)); + param->status = ERROR_FILE_NOT_FOUND; + } else { + bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t)); + param->status = ERROR_SUCCESS; + } + return (MLRPC_DRC_OK); } @@ -294,9 +362,9 @@ static int winreg_s_QueryKey(void *arg, struct mlrpc_xaction *mxa) { static char nullstr[2] = { 0, 0 }; - struct msreg_QueryKey *param = arg; + struct winreg_QueryKey *param = arg; - bzero(param, sizeof (struct msreg_QueryKey)); + bzero(param, sizeof (struct winreg_QueryKey)); param->name.length = 2; param->name.allosize = 0; @@ -311,15 +379,15 @@ winreg_s_QueryKey(void *arg, struct mlrpc_xaction *mxa) * This is a request to get the value associated with a specified name. * * Returns: - * ERROR_SUCCESS Value returned. + * ERROR_SUCCESS Value returned. * ERROR_FILE_NOT_FOUND PrimaryModule is not supported. * ERROR_CANTREAD No such name or memory problem. */ static int winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_QueryValue *param = arg; - struct msreg_value *pv; + struct winreg_QueryValue *param = arg; + struct winreg_value *pv; char *name; char *value; DWORD slen; @@ -338,9 +406,9 @@ winreg_s_QueryValue(void *arg, struct mlrpc_xaction *mxa) } slen = mts_wcequiv_strlen(value) + sizeof (mts_wchar_t); - msize = sizeof (struct msreg_value) + slen; + msize = sizeof (struct winreg_value) + slen; - param->value = (struct msreg_value *)MLRPC_HEAP_MALLOC(mxa, msize); + param->value = (struct winreg_value *)MLRPC_HEAP_MALLOC(mxa, msize); param->type = MLRPC_HEAP_NEW(mxa, DWORD); param->value_size = MLRPC_HEAP_NEW(mxa, DWORD); param->value_size_total = MLRPC_HEAP_NEW(mxa, DWORD); @@ -408,13 +476,26 @@ winreg_lookup_value(const char *name) } /* + * winreg_s_SetKeySec + */ +/*ARGSUSED*/ +static int +winreg_s_SetKeySec(void *arg, struct mlrpc_xaction *mxa) +{ + struct winreg_SetKeySec *param = arg; + + param->status = ERROR_ACCESS_DENIED; + return (MLRPC_DRC_OK); +} + +/* * winreg_s_CreateValue */ /*ARGSUSED*/ static int winreg_s_CreateValue(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_CreateValue *param = arg; + struct winreg_CreateValue *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -429,7 +510,7 @@ winreg_s_CreateValue(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_Shutdown(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_Shutdown *param = arg; + struct winreg_Shutdown *param = arg; param->status = ERROR_ACCESS_DENIED; return (MLRPC_DRC_OK); @@ -446,7 +527,7 @@ winreg_s_Shutdown(void *arg, struct mlrpc_xaction *mxa) static int winreg_s_GetVersion(void *arg, struct mlrpc_xaction *mxa) { - struct msreg_GetVersion *param = arg; + struct winreg_GetVersion *param = arg; param->version = 5; param->status = ERROR_SUCCESS; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c index b7453b171e..294acef207 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_wkssvc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,7 +84,7 @@ wkssvc_s_NetWkstaGetInfo(void *arg, struct mlrpc_xaction *mxa) struct mslm_NetWkstaGetInfo *param = arg; mslm_NetWkstaGetInfo_rb *rb; char hostname[MAXHOSTNAMELEN]; - char *resource_domain; + char resource_domain[SMB_PI_MAX_DOMAIN]; char *p; DWORD status; int rc; @@ -113,16 +113,12 @@ wkssvc_s_NetWkstaGetInfo(void *arg, struct mlrpc_xaction *mxa) } rb->buf100.wki100_computername = (unsigned char *)p; - smb_config_rdlock(); - resource_domain = smb_config_getstr(SMB_CI_DOMAIN_NAME); - + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); if ((p = MLRPC_HEAP_STRSAVE(mxa, resource_domain)) == NULL) { - smb_config_unlock(); status = ERROR_NOT_ENOUGH_MEMORY; break; } - smb_config_unlock(); rb->buf100.wki100_langroup = (unsigned char *)p; status = ERROR_SUCCESS; break; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c index 1b26087fb8..c385d837b8 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_auth.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -292,7 +292,6 @@ netr_gen_session_key(netr_info_t *netr_info) DWORD *client_challenge; DWORD *server_challenge; int rc; - char *machine_passwd; DWORD le_data[2]; client_challenge = (DWORD *)(uintptr_t)&netr_info->client_challenge; @@ -304,20 +303,15 @@ netr_gen_session_key(netr_info_t *netr_info) * the appropriate password but it isn't working yet. So we * always use the default one for now. */ - smb_config_rdlock(); - machine_passwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD); + bzero(netr_info->password, sizeof (netr_info->password)); + rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, + (char *)netr_info->password, sizeof (netr_info->password)); - if (!machine_passwd || *machine_passwd == 0) { - smb_config_unlock(); + if ((rc != SMBD_SMF_OK) || *netr_info->password == '\0') { return (-1); } - bzero(netr_info->password, sizeof (netr_info->password)); - (void) strlcpy((char *)netr_info->password, (char *)machine_passwd, - sizeof (netr_info->password)); - - rc = smb_auth_ntlm_hash((char *)machine_passwd, md4hash); - smb_config_unlock(); + rc = smb_auth_ntlm_hash((char *)netr_info->password, md4hash); if (rc != SMBAUTH_SUCCESS) return (SMBAUTH_FAILURE); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c index 93079001e9..152d97cd85 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/netr_logon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,6 +38,7 @@ #include <netdb.h> #include <smbsrv/libsmb.h> +#include <smbsrv/libsmbrdr.h> #include <smbsrv/ndl/netlogon.ndl> #include <smbsrv/mlsvc_util.h> #include <smbsrv/mlsvc.h> @@ -94,32 +95,18 @@ netlogon_logon(netr_client_t *clnt, smb_userinfo_t *user_info) DWORD status; int retries = 0; - smb_config_rdlock(); - (void) strlcpy(resource_domain, smb_config_getstr(SMB_CI_DOMAIN_NAME), - sizeof (resource_domain)); - smb_config_unlock(); + (void) smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN); - /* - * If the SMB info cache is not valid, - * try to locate a domain controller. - */ - if ((di = smb_getdomaininfo(0)) == NULL) { - (void) mlsvc_locate_domain_controller(resource_domain); - - if ((di = smb_getdomaininfo(0)) == NULL) - return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); - } + if ((di = smb_getdomaininfo(0)) == NULL) + return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); if ((mlsvc_echo(di->server)) < 0) { /* * We had a session to the DC but it's not responding. - * So drop the credential chain and find another DC. + * So drop the credential chain. */ netr_invalidate_chain(); - (void) mlsvc_locate_domain_controller(resource_domain); - - if ((di = smb_getdomaininfo(0)) == NULL) - return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); + return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } do { diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c index ef303a8b21..1e8e533721 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samlib.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samlib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,99 +50,6 @@ #define SAM_KEYLEN 16 extern DWORD samr_set_user_info(mlsvc_handle_t *, smb_auth_info_t *); -static int get_user_group_info(mlsvc_handle_t *, smb_userinfo_t *); - -/* - * sam_lookup_user_info - * - * Lookup user information in the SAM database on the specified server - * (domain controller). The LSA interface is used to obtain the user - * RID, the domain name and the domain SID (user privileges are TBD). - * Then the various SAM layers are opened using the domain SID and the - * user RID to obtain the users's group membership information. - * - * The information is returned in the user_info structure. The caller - * is responsible for allocating and releasing this structure. If the - * lookup is successful, sid_name_use will be set to SidTypeUser. - * - * On success 0 is returned. Otherwise a -ve error code. - */ -int -sam_lookup_user_info(char *server, char *domain_name, - char *account_name, smb_userinfo_t *user_info) -{ - mlsvc_handle_t samr_handle; - mlsvc_handle_t domain_handle; - mlsvc_handle_t user_handle; - struct samr_sid *sid; - int rc; - DWORD access_mask; - DWORD status; - - if (lsa_lookup_name(server, domain_name, account_name, user_info) != 0) - return (-1); - - if (user_info->sid_name_use != SidTypeUser || - user_info->rid == 0 || user_info->domain_sid == 0) { - return (-1); - } - - rc = samr_open(server, domain_name, account_name, - SAM_LOOKUP_INFORMATION, &samr_handle); - if (rc != 0) - return (-1); - sid = (struct samr_sid *)user_info->domain_sid; - - status = samr_open_domain(&samr_handle, SAM_LOOKUP_INFORMATION, - sid, &domain_handle); - if (status == 0) { - access_mask = STANDARD_RIGHTS_EXECUTE | SAM_ACCESS_USER_READ; - - status = samr_open_user(&domain_handle, access_mask, - user_info->rid, &user_handle); - - if (status == NT_STATUS_SUCCESS) { - (void) get_user_group_info(&user_handle, user_info); - (void) samr_close_handle(&user_handle); - } else { - rc = -1; - } - - (void) samr_close_handle(&domain_handle); - } else { - rc = -1; - } - - (void) samr_close_handle(&samr_handle); - return (rc); -} - -/* - * get_user_group_info - * - * This is a private function to obtain the primary group and group - * memberships for the user specified by the user_handle. This function - * should only be called from sam_lookup_user_info. - * - * On success 0 is returned. Otherwise -1 is returned. - */ -static int -get_user_group_info(mlsvc_handle_t *user_handle, smb_userinfo_t *user_info) -{ - union samr_user_info sui; - int rc; - - rc = samr_query_user_info(user_handle, SAMR_QUERY_USER_GROUPRID, &sui); - if (rc != 0) - return (-1); - - rc = samr_query_user_groups(user_handle, user_info); - if (rc != 0) - return (-1); - - user_info->primary_group_rid = sui.info9.group_rid; - return (0); -} /* * sam_create_trust_account @@ -157,7 +64,6 @@ get_user_group_info(mlsvc_handle_t *user_handle, smb_userinfo_t *user_info) DWORD sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) { - smb_userinfo_t *user_info; char account_name[MAXHOSTNAMELEN]; DWORD status; @@ -166,19 +72,13 @@ sam_create_trust_account(char *server, char *domain, smb_auth_info_t *auth) (void) strlcat(account_name, "$", MAXHOSTNAMELEN); - if ((user_info = mlsvc_alloc_user_info()) == 0) - return (NT_STATUS_NO_MEMORY); - /* * The trust account value here should match * the value that will be used when the user * information is set on this account. */ status = sam_create_account(server, domain, account_name, - auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT, user_info); - - mlsvc_free_user_info(user_info); - + auth, SAMR_AF_WORKSTATION_TRUST_ACCOUNT); /* * Based on network traces, a Windows 2000 client will @@ -209,11 +109,12 @@ 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, smb_userinfo_t *user_info) + smb_auth_info_t *auth, DWORD account_flags) { 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; @@ -221,6 +122,9 @@ sam_create_account(char *server, char *domain_name, char *account_name, 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); @@ -228,6 +132,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, 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); } @@ -242,6 +147,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, smb_tracef("SamCreateAccount[%s\\%s]: %s", domain_name, account_name, xlate_nt_status(status)); + mlsvc_free_user_info(user_info); return (status); } } @@ -254,6 +160,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, smb_tracef("SamCreateAccount[%s]: lookup failed", account_name); + mlsvc_free_user_info(user_info); return (NT_STATUS_CANT_ACCESS_DOMAIN_INFO); } @@ -274,14 +181,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, (void) samr_get_user_pwinfo(&user_handle); (void) samr_set_user_info(&user_handle, auth); (void) samr_close_handle(&user_handle); - } else if (status == NT_STATUS_USER_EXISTS) { - mlsvc_release_user_info(user_info); - - rc = lsa_lookup_name(server, domain_name, account_name, - user_info); - if (rc == 0) - rid = user_info->rid; - } else { + } else if (status != NT_STATUS_USER_EXISTS) { smb_tracef("SamCreateAccount[%s]: %s", account_name, xlate_nt_status(status)); } @@ -294,6 +194,7 @@ sam_create_account(char *server, char *domain_name, char *account_name, } (void) samr_close_handle(&samr_handle); + mlsvc_free_user_info(user_info); return (status); } diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c index e20b6404d7..463cd7f223 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_lookup.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -473,7 +473,7 @@ samr_set_user_unknowns(struct samr_SetUserInfo23 *info) info->sd.length = 0; info->sd.data = 0; info->user_rid = 0; - info->group_rid = MLSVC_DOMAIN_GROUP_RID_USERS; + info->group_rid = DOMAIN_GROUP_RID_USERS; /* * The trust account value used here should probably diff --git a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c index 233acdf84d..015165798f 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/samr_open.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -318,7 +318,7 @@ samr_connect4(char *server, char *domain, char *username, DWORD access_mask, { struct samr_Connect4 arg; mlrpc_heapref_t heapref; - char *dns_name; + char dns_name[MAXHOSTNAMELEN]; int len; int opnum; DWORD status; @@ -327,9 +327,10 @@ samr_connect4(char *server, char *domain, char *username, DWORD access_mask, opnum = SAMR_OPNUM_Connect; status = NT_STATUS_SUCCESS; + if (smb_resolve_fqdn(domain, dns_name, MAXHOSTNAMELEN) != 1) + return (NT_STATUS_UNSUCCESSFUL); + (void) mlsvc_rpc_init(&heapref); - dns_name = mlrpc_heap_malloc(heapref.heap, MAXHOSTNAMELEN); - (void) smb_getdomainname(dns_name, MAXHOSTNAMELEN); if (strlen(dns_name) > 0) { len = strlen(server) + strlen(dns_name) + 4; diff --git a/usr/src/lib/smbsrv/libmlsvc/common/secdb.c b/usr/src/lib/smbsrv/libmlsvc/common/secdb.c index cc4d96456f..1c46a89504 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/secdb.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/secdb.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -338,23 +338,36 @@ static smb_privset_t * smb_token_create_privs(smb_userinfo_t *user_info) { smb_privset_t *privs; - nt_group_t *grp; + smb_giter_t gi; + smb_group_t grp; + int rc; privs = smb_privset_new(); if (privs == NULL) return (NULL); - (void) nt_groups_member_privs(user_info->user_sid, privs); + if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) { + smb_privset_free(privs); + return (NULL); + } + + while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, user_info->user_sid)) { + smb_privset_merge(privs, grp.sg_privs); + } + smb_lgrp_free(&grp); + } + smb_lgrp_iterclose(&gi); if (user_info->flags & SMB_UINFO_FLAG_ADMIN) { - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - nt_group_add_groupprivs(grp, privs); - nt_group_putinfo(grp); + rc = smb_lgrp_getbyname("Administrators", &grp); + if (rc == SMB_LGRP_SUCCESS) { + smb_privset_merge(privs, grp.sg_privs); + smb_lgrp_free(&grp); } /* - * This privilege is required for view/edit of SACL + * This privilege is required to view/edit SACL */ smb_privset_enable(privs, SE_SECURITY_LUID); } @@ -513,6 +526,8 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) smb_rid_attrs_t *g_grps; smb_sid_attrs_t *grp; nt_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; @@ -524,7 +539,7 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) n_dlg = user_info->n_other_grps; /* Domain Local Groups */ /* Local Groups */ - n_lg = nt_groups_member_ngroups(user_info->user_sid); + (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) @@ -538,20 +553,18 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) count = n_gg + n_dlg + n_lg + n_wg; size = sizeof (smb_win_grps_t) + (count * sizeof (smb_id_t)); - tkn_grps = (smb_win_grps_t *)malloc(size); - if (tkn_grps == NULL) { + if ((tkn_grps = malloc(size)) == NULL) return (NULL); - } bzero(tkn_grps, size); - tkn_grps->wg_count = count; - /* Add global groups */ g_grps = user_info->groups; - for (i = 0; i < n_gg; ++i) { + for (i = 0; i < n_gg; i++) { grp = &tkn_grps->wg_groups[i].i_sidattr; - grp->attrs = g_grps[i].attributes; grp->sid = nt_sid_splice(user_info->domain_sid, g_grps[i].rid); + if (grp->sid == NULL) + break; + grp->attrs = g_grps[i].attributes; } if (n_gg == 0) { @@ -559,34 +572,55 @@ smb_token_create_wingrps(smb_userinfo_t *user_info) * if there's no global group should add the * primary group. */ - grp = &tkn_grps->wg_groups[i++].i_sidattr; - grp->attrs = 0x7; + grp = &tkn_grps->wg_groups[i].i_sidattr; grp->sid = nt_sid_dup(user_info->pgrp_sid); - tkn_grps->wg_count++; + 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) { + for (j = 0; j < n_dlg; j++, i++) { grp = &tkn_grps->wg_groups[i].i_sidattr; - grp->attrs = dlg_grps[j].attrs; grp->sid = nt_sid_dup(dlg_grps[j].sid); + if (grp->sid == NULL) + break; + grp->attrs = dlg_grps[j].attrs; } - if (n_lg) { - /* Add local groups */ - (void) nt_groups_member_groups(user_info->user_sid, - &tkn_grps->wg_groups[i], n_lg); - i += n_lg; + /* 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 = nt_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) { + for (j = 0; j < n_wg; j++, i++) { builtin_sid = nt_builtin_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); } @@ -698,6 +732,7 @@ smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo) &smbpw, clnt->lm_password.lm_password_val, clnt->lm_password.lm_password_len, + clnt->domain, clnt->username); } @@ -708,6 +743,7 @@ smb_logon_local(netr_client_t *clnt, smb_userinfo_t *uinfo) &smbpw, clnt->nt_password.nt_password_val, clnt->nt_password.nt_password_len, + clnt->domain, clnt->username); } @@ -747,7 +783,7 @@ smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid) idmap_stat stat; smb_idmap_batch_t sib; smb_idmap_t *umap, *gmap; - nt_group_t *grp; + smb_group_t grp; struct passwd pw; char pwbuf[1024]; @@ -820,11 +856,10 @@ smb_setup_luinfo(smb_userinfo_t *lui, netr_client_t *clnt, uid_t uid) if ((lui->user_sid == NULL) || (lui->pgrp_sid == NULL)) return (NT_STATUS_NO_MEMORY); - grp = nt_group_getinfo("Administrators", RWLOCK_READER); - if (grp) { - if (nt_group_is_member(grp, lui->user_sid)) + if (smb_lgrp_getbyname("Administrators", &grp) == SMB_LGRP_SUCCESS) { + if (smb_lgrp_is_member(&grp, lui->user_sid)) lui->flags = SMB_UINFO_FLAG_LADMIN; - nt_group_putinfo(grp); + smb_lgrp_free(&grp); } return (NT_STATUS_SUCCESS); diff --git a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c index 6d0610add3..bc3f526046 100644 --- a/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_autohome.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -224,8 +224,9 @@ void smb_autohome_setent(void) { smb_autohome_info_t *si; - char *mappath; + char path[MAXNAMELEN]; char filename[MAXNAMELEN]; + int rc; if ((si = smb_autohome_getinfo()) != 0) { (void) fseek(si->fp, 0L, SEEK_SET); @@ -236,12 +237,12 @@ smb_autohome_setent(void) if ((si = &smb_ai) == 0) return; - smb_config_rdlock(); - if ((mappath = smb_config_get(SMB_CI_AUTOHOME_MAP)) == NULL) - mappath = SMB_AUTOHOME_PATH; - (void) snprintf(filename, MAXNAMELEN, "%s/%s", mappath, + rc = smb_config_getstr(SMB_CI_AUTOHOME_MAP, path, sizeof (path)); + if (rc != SMBD_SMF_OK) + return; + + (void) snprintf(filename, MAXNAMELEN, "%s/%s", path, SMB_AUTOHOME_FILE); - smb_config_unlock(); if ((si->fp = fopen(filename, "r")) == NULL) return; diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com index 3771f7d993..857605eb72 100644 --- a/usr/src/lib/smbsrv/libsmb/Makefile.com +++ b/usr/src/lib/smbsrv/libsmb/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -56,11 +56,10 @@ OBJS_COMMON = \ smb_door_encdec.o \ smb_doorclnt.o \ smb_downcalls.o \ - smb_group_door_encdec.o \ - smb_group_xdr.o \ smb_ht.o \ smb_idmap.o \ smb_info.o \ + smb_lgrp.o \ smb_mac.o \ smb_pwdutil.o \ smb_privilege.o \ @@ -77,7 +76,7 @@ include ../../Makefile.lib INCS += -I$(SRC)/common/smbsrv LDLIBS += $(MACH_LDLIBS) -LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lidmap +LDLIBS += -lscf -lmd -lnsl -lpkcs11 -lc -lresolv -lidmap CPPFLAGS += $(INCS) -D_REENTRANT SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \ diff --git a/usr/src/lib/smbsrv/libsmb/amd64/Makefile b/usr/src/lib/smbsrv/libsmb/amd64/Makefile index b3c4916b0c..03c6ea5b61 100644 --- a/usr/src/lib/smbsrv/libsmb/amd64/Makefile +++ b/usr/src/lib/smbsrv/libsmb/amd64/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index 510f68c20d..50a3c3d989 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,11 +34,14 @@ extern "C" { #include <sys/types.h> #include <arpa/inet.h> +#include <netdb.h> #include <stdlib.h> #include <libscf.h> #include <libshare.h> +#include <sqlite/sqlite.h> +#include <smbsrv/string.h> #include <smbsrv/smb_idmap.h> /* @@ -67,7 +70,6 @@ extern "C" { /* Max value length of all SMB properties */ #define MAX_VALUE_BUFLEN 512 -#define SMB_PI_MAX_DOMAIN_U 48 #define SMBD_FMRI_PREFIX "network/smb/server" #define SMBD_DEFAULT_INSTANCE_FMRI "svc:/network/smb/server:default" @@ -78,6 +80,7 @@ extern "C" { #define SMBD_SMF_NO_MEMORY 1 /* no memory for data structures */ #define SMBD_SMF_SYSTEM_ERR 2 /* system error, use errno */ #define SMBD_SMF_NO_PERMISSION 3 /* no permission for operation */ +#define SMBD_SMF_INVALID_ARG 4 #define SCH_STATE_UNINIT 0 #define SCH_STATE_INITIALIZING 1 @@ -99,72 +102,8 @@ typedef struct smb_scfhandle { /* * CIFS Configuration Management */ - -/* macros for the description of all config params */ -#define SMB_CD_RDR_IPCMODE "rdr_ipcmode" -#define SMB_CD_RDR_IPCUSER "rdr_ipcuser" -#define SMB_CD_RDR_IPCPWD "rdr_ipcpasswd" - -#define SMB_CD_OPLOCK_ENABLE "oplock_enable" -#define SMB_CD_OPLOCK_TIMEOUT "oplock_timeout" - -#define SMB_CD_AUTOHOME_MAP "autohome_map" - -#define SMB_CD_DOMAIN_SID "domain_sid" -#define SMB_CD_DOMAIN_MEMB "domain_member" -#define SMB_CD_DOMAIN_NAME "domain_name" -#define SMB_CD_DOMAIN_SRV "pdc" - -#define SMB_CD_WINS_SRV1 "wins_server_1" -#define SMB_CD_WINS_SRV2 "wins_server_2" -#define SMB_CD_WINS_EXCL "wins_exclude" - -#define SMB_CD_SRVSVC_SHRSET_ENABLE "srvsvc_sharesetinfo_enable" -#define SMB_CD_LOGR_ENABLE "logr_enable" -#define SMB_CD_MLRPC_KALIVE "mlrpc_keep_alive_interval" - -#define SMB_CD_MAX_BUFSIZE "max_bufsize" -#define SMB_CD_MAX_WORKERS "max_workers" -#define SMB_CD_MAX_CONNECTIONS "max_connections" -#define SMB_CD_KEEPALIVE "keep_alive" -#define SMB_CD_RESTRICT_ANON "restrict_anonymous" - -#define SMB_CD_SIGNING_ENABLE "signing_enabled" -#define SMB_CD_SIGNING_REQD "signing_required" -#define SMB_CD_SIGNING_CHECK "signing_check" - -#define SMB_CD_FLUSH_REQUIRED "flush_required" -#define SMB_CD_SYNC_ENABLE "sync_enable" -#define SMB_CD_DIRSYMLINK_DISABLE "dir_symlink_disable" -#define SMB_CD_ANNONCE_QUOTA "announce_quota" - -#define SMB_CD_SECURITY "security" -#define SMB_CD_NBSCOPE "netbios_scope" -#define SMB_CD_SYS_CMNT "system_comment" -#define SMB_CD_LM_LEVEL "lmauth_level" -#define SMB_CD_MSDCS_DISABLE "msdcs_disable" - -#define SMB_CD_ADS_ENABLE "ads_enable" -#define SMB_CD_ADS_USER "ads_user" -#define SMB_CD_ADS_PASSWD "ads_passwd" -#define SMB_CD_ADS_DOMAIN "ads_domain" -#define SMB_CD_ADS_USER_CONTAINER "ads_user_container" -#define SMB_CD_ADS_SITE "ads_site" -#define SMB_CD_ADS_IPLOOKUP "ads_ip_lookup" - -#define SMB_CD_DYNDNS_ENABLE "ddns_enable" -#define SMB_CD_DYNDNS_RETRY_COUNT "ddns_retry_cnt" -#define SMB_CD_DYNDNS_RETRY_SEC "ddns_retry_sec" - -#define SMB_CD_MACHINE_PASSWD "machine_passwd" - -/* configuration identifier */ typedef enum { - SMB_CI_RDR_IPCMODE = 0, - SMB_CI_RDR_IPCUSER, - SMB_CI_RDR_IPCPWD, - - SMB_CI_OPLOCK_ENABLE, + SMB_CI_OPLOCK_ENABLE = 0, SMB_CI_OPLOCK_TIMEOUT, SMB_CI_AUTOHOME_MAP, @@ -179,7 +118,6 @@ typedef enum { SMB_CI_WINS_EXCL, SMB_CI_SRVSVC_SHRSET_ENABLE, - SMB_CI_LOGR_ENABLE, SMB_CI_MLRPC_KALIVE, SMB_CI_MAX_BUFSIZE, @@ -201,19 +139,10 @@ typedef enum { SMB_CI_NBSCOPE, SMB_CI_SYS_CMNT, SMB_CI_LM_LEVEL, - SMB_CI_MSDCS_DISABLE, - SMB_CI_ADS_ENABLE, - SMB_CI_ADS_USER, - SMB_CI_ADS_PASSWD, - SMB_CI_ADS_DOMAIN, - SMB_CI_ADS_USER_CONTAINER, SMB_CI_ADS_SITE, - SMB_CI_ADS_IPLOOKUP, SMB_CI_DYNDNS_ENABLE, - SMB_CI_DYNDNS_RETRY_COUNT, - SMB_CI_DYNDNS_RETRY_SEC, SMB_CI_MACHINE_PASSWD, SMB_CI_MAX @@ -236,41 +165,20 @@ extern int smb_smf_set_opaque_property(smb_scfhandle_t *, char *, extern int smb_smf_get_opaque_property(smb_scfhandle_t *, char *, void *, size_t); extern int smb_smf_create_service_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_service_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_create_instance_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_instance_pgroup(smb_scfhandle_t *, char *); -extern int smb_smf_delete_property(smb_scfhandle_t *, char *); -extern int smb_smf_instance_exists(smb_scfhandle_t *, char *); -extern int smb_smf_instance_create(smb_scfhandle_t *, char *, char *); -extern int smb_smf_instance_delete(smb_scfhandle_t *, char *); -extern smb_scfhandle_t *smb_smf_get_iterator(char *); -extern int smb_smf_get_property(smb_scfhandle_t *, int, char *, char *, - size_t); -extern int smb_smf_set_property(smb_scfhandle_t *, int, char *, char *); /* Configuration management functions */ -extern int smb_config_load(void); -extern void smb_config_rdlock(void); -extern void smb_config_wrlock(void); -extern void smb_config_unlock(void); -extern char *smb_config_get(smb_cfg_id_t); -extern char *smb_config_getstr(smb_cfg_id_t); -extern int smb_config_getyorn(smb_cfg_id_t); -extern uint32_t smb_config_getnum(smb_cfg_id_t); - -/* - * smb_config_getenv - * - * Retrieves the property value from SMF. - * Caller must free the returned buffer. - * - */ -extern char *smb_config_getenv(smb_cfg_id_t id); +extern int smb_config_get(smb_cfg_id_t, char *, int); +extern char *smb_config_getname(smb_cfg_id_t); +extern int smb_config_getstr(smb_cfg_id_t, char *, int); +extern int smb_config_getnum(smb_cfg_id_t, int64_t *); +extern boolean_t smb_config_getbool(smb_cfg_id_t); extern int smb_config_set(smb_cfg_id_t, char *); -extern int smb_config_setnum(smb_cfg_id_t, uint32_t); +extern int smb_config_setstr(smb_cfg_id_t, char *); +extern int smb_config_setnum(smb_cfg_id_t, int64_t); +extern int smb_config_setbool(smb_cfg_id_t, boolean_t); + extern uint8_t smb_config_get_fg_flag(void); -extern int smb_config_setenv(smb_cfg_id_t id, char *); extern char *smb_config_get_localsid(void); extern int smb_config_secmode_fromstr(char *secmode); extern char *smb_config_secmode_tostr(int secmode); @@ -283,7 +191,7 @@ extern int smb_config_refresh(void); /* smb_door_client.c */ typedef struct smb_joininfo { - char domain_name[SMB_PI_MAX_DOMAIN]; + char domain_name[MAXHOSTNAMELEN]; char domain_username[BUF_LEN + 1]; char domain_passwd[BUF_LEN + 1]; uint32_t mode; @@ -293,10 +201,8 @@ typedef struct smb_joininfo { extern int smbd_set_param(smb_cfg_id_t, char *); extern int smbd_get_param(smb_cfg_id_t, char *); extern int smbd_get_security_mode(int *); -extern int smb_set_machine_pwd(char *); extern int smbd_netbios_reconfig(void); extern uint32_t smb_join(smb_joininfo_t *info); -extern int smb_ads_domain_change_notify(char *); #define SMB_DOMAIN_NOMACHINE_SID -1 @@ -317,22 +223,15 @@ extern int smb_wins_iplist(char *list, uint32_t iplist[], int max_naddr); * name of a controller (PDC or BDC) and it's ip address. */ typedef struct smb_ntdomain { - char domain[SMB_PI_MAX_DOMAIN_U]; - char server[SMB_PI_MAX_DOMAIN_U]; + char domain[SMB_PI_MAX_DOMAIN]; + char server[SMB_PI_MAX_DOMAIN]; uint32_t ipaddr; } smb_ntdomain_t; /* SMB domain information management functions */ -extern void smb_purge_domain_info(void); -extern int smb_is_domain_member(void); -extern uint8_t smb_get_fg_flag(void); -extern void smb_set_domain_member(int set); extern smb_ntdomain_t *smb_getdomaininfo(uint32_t timeout); extern void smb_setdomaininfo(char *domain, char *server, uint32_t ipaddr); extern void smb_logdomaininfo(smb_ntdomain_t *di); -extern uint32_t smb_get_security_mode(void); - -extern int nt_priv_presentable_num(void); /* * Following set of function, handle calls to SMB Kernel driver, via @@ -373,9 +272,12 @@ extern char *trim_whitespace(char *buf); extern void randomize(char *, unsigned); extern void rand_hash(unsigned char *, size_t, unsigned char *, size_t); +extern int smb_resolve_netbiosname(char *, char *, size_t); +extern int smb_resolve_fqdn(char *, char *, size_t); extern int smb_getdomainname(char *, size_t); -extern int smb_getfqhostname(char *, size_t); +extern int smb_getfqdomainname(char *, size_t); extern int smb_gethostname(char *, size_t, int); +extern int smb_getfqhostname(char *, size_t); extern int smb_getnetbiosname(char *, size_t); void smb_trace(const char *s); @@ -493,14 +395,6 @@ typedef struct smb_auth_info { smb_auth_data_blob_t data_blob; } smb_auth_info_t; -extern int smb_getdomainname(char *, size_t); -extern int smb_getfqhostname(char *, size_t); -extern int smb_gethostname(char *, size_t, int); -extern int smb_getnetbiosname(char *, size_t); - -void smb_trace(const char *s); -void smb_tracef(const char *fmt, ...); - /* * SMB password management */ @@ -567,9 +461,9 @@ extern int smb_auth_set_info(char *, char *, extern int smb_auth_gen_session_key(smb_auth_info_t *, unsigned char *); boolean_t smb_auth_validate_lm(unsigned char *, uint32_t, smb_passwd_t *, - unsigned char *, int, char *); + unsigned char *, int, char *, char *); boolean_t smb_auth_validate_nt(unsigned char *, uint32_t, smb_passwd_t *, - unsigned char *, int, char *); + unsigned char *, int, char *, char *); /* * SMB MAC Signing @@ -682,97 +576,94 @@ nt_domain_t *nt_domain_lookup_sid(nt_sid_t *domain_sid); nt_domain_t *nt_domain_lookupbytype(nt_domain_type_t type); nt_sid_t *nt_domain_local_sid(void); -#define SMB_GROUP_PER_LIST 5 - -/* - * This structure takes different args passed from the client/server routines - * of the SMB local group door service. Extend this structure if a new type - * client paramater needs to be passed. - */ -typedef struct ntgrp_dr_arg { - char *gname; - char *desc; - char *member; - char *newgname; - uint32_t privid; - uint32_t priv_attr; - int offset; - char *scope; - int type; - int count; - uint32_t ntstatus; -} ntgrp_dr_arg_t; - -typedef struct ntgrp { - DWORD rid; /* Rid of the group */ - char *name; /* Name of the group */ - char *desc; /* Desc of gruup */ - char *type; /* sid_name_use */ - char *sid; /* Sid */ - DWORD attr; /* Attribute */ -} ntgrp_t; - -typedef struct ntgrp_list { - int cnt; - ntgrp_t groups[SMB_GROUP_PER_LIST]; -} ntgrp_list_t; - -typedef char *members_list; -typedef struct ntgrp_member_list { - DWORD rid; /* Rid of the group in which members belong */ - int cnt; /* members */ - members_list members[SMB_GROUP_PER_LIST]; -} ntgrp_member_list_t; - -typedef struct ntpriv { - DWORD id; /* Id of priv */ - char *name; /* Name of priv */ -} ntpriv_t; -typedef ntpriv_t *privs_t; - -typedef struct ntpriv_list { - int cnt; /* Number of privs */ - privs_t privs[ANY_SIZE_ARRAY]; /* privs only presentable ones */ -} ntpriv_list_t; - - -/* the xdr functions */ -extern bool_t xdr_ntgrp_dr_arg_t(XDR *, ntgrp_dr_arg_t *); -extern bool_t xdr_ntgrp_t(XDR *, ntgrp_t *); -extern bool_t xdr_ntgrp_list_t(XDR *, ntgrp_list_t *); -extern bool_t xdr_members_list(XDR *, members_list *); -extern bool_t xdr_ntgrp_member_list_t(XDR *, ntgrp_member_list_t *); -extern bool_t xdr_ntpriv_t(XDR *, ntpriv_t *); -extern bool_t xdr_privs_t(XDR *, privs_t *); -extern bool_t xdr_ntpriv_list_t(XDR *, ntpriv_list_t *); - -extern void smb_group_free_memberlist(ntgrp_member_list_t *, int); -extern void smb_group_free_list(ntgrp_list_t *, int); -extern void smb_group_free_privlist(ntpriv_list_t *, int); - -extern uint32_t smb_group_add(char *, char *); -extern uint32_t smb_group_modify(char *, char *, char *); -extern uint32_t smb_group_delete(char *); -extern uint32_t smb_group_member_remove(char *, char *); -extern uint32_t smb_group_member_add(char *, char *); -extern uint32_t smb_group_priv_num(int *); -extern uint32_t smb_group_priv_list(ntpriv_list_t **); -extern uint32_t smb_group_priv_get(char *, uint32_t, uint32_t *); -extern uint32_t smb_group_priv_set(char *, uint32_t, uint32_t); -extern uint32_t smb_group_count(int *); -extern uint32_t smb_group_list(int, ntgrp_list_t **, char *, int); -extern uint32_t smb_group_member_count(char *, int *); -extern uint32_t smb_group_member_list(char *, int, ntgrp_member_list_t **); - -extern char *smb_dr_encode_grp_privlist(uint32_t, ntpriv_list_t *, size_t *); -extern ntpriv_list_t *smb_dr_decode_grp_privlist(char *, size_t); - -extern char *smb_dr_encode_grp_list(uint32_t, ntgrp_list_t *, size_t *); -extern ntgrp_list_t *smb_dr_decode_grp_list(char *, size_t); - -extern char *smb_dr_encode_grp_memberlist(uint32_t, ntgrp_member_list_t *, - size_t *); -extern ntgrp_member_list_t *smb_dr_decode_grp_memberlist(char *buf, size_t len); +typedef enum { + SMB_LGRP_BUILTIN = 1, + SMB_LGRP_LOCAL +} smb_gdomain_t; + +typedef struct smb_gsid { + nt_sid_t *gs_sid; + uint16_t gs_type; +} smb_gsid_t; + +typedef struct smb_giter { + sqlite_vm *sgi_vm; + sqlite *sgi_db; +} smb_giter_t; + +typedef struct smb_group { + char *sg_name; + char *sg_cmnt; + uint32_t sg_attr; + uint32_t sg_rid; + smb_gsid_t sg_id; + smb_gdomain_t sg_domain; + smb_privset_t *sg_privs; + uint32_t sg_nmembers; + smb_gsid_t *sg_members; +} smb_group_t; + +int smb_lgrp_start(void); +void smb_lgrp_stop(void); +int smb_lgrp_add(char *, char *); +int smb_lgrp_rename(char *, char *); +int smb_lgrp_delete(char *); +int smb_lgrp_setcmnt(char *, char *); +int smb_lgrp_getcmnt(char *, char **); +int smb_lgrp_getpriv(char *, uint8_t, boolean_t *); +int smb_lgrp_setpriv(char *, uint8_t, boolean_t); +int smb_lgrp_add_member(char *, nt_sid_t *, uint16_t); +int smb_lgrp_del_member(char *, nt_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(nt_sid_t *, int *); +void smb_lgrp_free(smb_group_t *); +boolean_t smb_lgrp_is_member(smb_group_t *, nt_sid_t *); +char *smb_lgrp_strerror(int); +int smb_lgrp_iteropen(smb_giter_t *); +void smb_lgrp_iterclose(smb_giter_t *); +int smb_lgrp_iterate(smb_giter_t *, smb_group_t *); + +int smb_lookup_sid(nt_sid_t *, char *buf, int buflen); +int smb_lookup_name(char *, smb_gsid_t *); + +#define SMB_LGRP_SUCCESS 0 +#define SMB_LGRP_INVALID_ARG 1 +#define SMB_LGRP_INVALID_MEMBER 2 +#define SMB_LGRP_INVALID_NAME 3 +#define SMB_LGRP_NOT_FOUND 4 +#define SMB_LGRP_EXISTS 5 +#define SMB_LGRP_NO_SID 6 +#define SMB_LGRP_NO_LOCAL_SID 7 +#define SMB_LGRP_SID_NOTLOCAL 8 +#define SMB_LGRP_WKSID 9 +#define SMB_LGRP_NO_MEMORY 10 +#define SMB_LGRP_DB_ERROR 11 +#define SMB_LGRP_DBINIT_ERROR 12 +#define SMB_LGRP_INTERNAL_ERROR 13 +#define SMB_LGRP_MEMBER_IN_GROUP 14 +#define SMB_LGRP_MEMBER_NOT_IN_GROUP 15 +#define SMB_LGRP_NO_SUCH_PRIV 16 +#define SMB_LGRP_NO_SUCH_DOMAIN 17 +#define SMB_LGRP_PRIV_HELD 18 +#define SMB_LGRP_PRIV_NOT_HELD 19 +#define SMB_LGRP_BAD_DATA 20 +#define SMB_LGRP_NO_MORE 21 +#define SMB_LGRP_DBOPEN_FAILED 22 +#define SMB_LGRP_DBEXEC_FAILED 23 +#define SMB_LGRP_DBINIT_FAILED 24 +#define SMB_LGRP_DOMLKP_FAILED 25 +#define SMB_LGRP_DOMINS_FAILED 26 +#define SMB_LGRP_INSERT_FAILED 27 +#define SMB_LGRP_DELETE_FAILED 28 +#define SMB_LGRP_UPDATE_FAILED 29 +#define SMB_LGRP_LOOKUP_FAILED 30 +#define SMB_LGRP_NOT_SUPPORTED 31 + +#define SMB_LGRP_NAME_CHAR_MAX 32 +#define SMB_LGRP_COMMENT_MAX 256 +#define SMB_LGRP_NAME_MAX (SMB_LGRP_NAME_CHAR_MAX * MTS_MB_CHAR_MAX + 1) #ifdef __cplusplus } diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index 3fa172f5d6..c5ad0f8219 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -18,7 +18,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -108,7 +108,6 @@ SUNWprivate { oemstounicodes; rand_hash; randomize; - smb_ads_domain_change_notify; smb_auth_DES; smb_auth_gen_session_key; smb_auth_ntlm_hash; @@ -120,12 +119,10 @@ SUNWprivate { smb_config_get_fg_flag; smb_config_get_localsid; smb_config_get_secmode; - smb_config_getenv; + smb_config_getbool; + smb_config_getname; smb_config_getnum; smb_config_getstr; - smb_config_getyorn; - smb_config_load; - smb_config_rdlock; smb_config_refresh; smb_config_refresh_idmap; smb_config_secmode_fromstr; @@ -133,26 +130,19 @@ SUNWprivate { smb_config_set; smb_config_set_idmap_domain; smb_config_set_secmode; - smb_config_setenv; + smb_config_setbool; smb_config_setnum; - smb_config_unlock; - smb_config_wrlock; + smb_config_setstr; smb_ctxbuf_init; smb_ctxbuf_len; smb_ctxbuf_printf; smb_dr_decode_arg_get_token; smb_dr_decode_common; smb_dr_decode_finish; - smb_dr_decode_grp_list; - smb_dr_decode_grp_memberlist; - smb_dr_decode_grp_privlist; smb_dr_decode_start; smb_dr_decode_string; smb_dr_encode_common; smb_dr_encode_finish; - smb_dr_encode_grp_list; - smb_dr_encode_grp_memberlist; - smb_dr_encode_grp_privlist; smb_dr_encode_res_token; smb_dr_encode_start; smb_dr_encode_string; @@ -193,41 +183,47 @@ SUNWprivate { smb_dwncall_install_callback; smb_dwncall_share; smb_dwncall_user_num; - smb_get_fg_flag; - smb_get_security_mode; smb_getdomaininfo; smb_getdomainname; + smb_getfqdomainname; smb_getfqhostname; smb_gethostname; smb_getnetbiosname; - smb_group_add; - smb_group_count; - smb_group_delete; - smb_group_free_list; - smb_group_free_memberlist; - smb_group_free_privlist; - smb_group_list; - smb_group_member_add; - smb_group_member_count; - smb_group_member_list; - smb_group_member_remove; - smb_group_modify; - smb_group_priv_get; - smb_group_priv_list; - smb_group_priv_num; - smb_group_priv_set; smb_idmap_batch_create; smb_idmap_batch_destroy; smb_idmap_batch_getid; smb_idmap_batch_getmappings; smb_idmap_batch_getsid; + smb_idmap_getid; smb_idmap_getsid; smb_idmap_restart; smb_idmap_start; smb_idmap_stop; - smb_is_domain_member; smb_join; + smb_lgrp_add; + smb_lgrp_add_member; + smb_lgrp_delete; + smb_lgrp_del_member; + smb_lgrp_free; + smb_lgrp_getbyname; + smb_lgrp_getbyrid; + smb_lgrp_getcmnt; + smb_lgrp_getpriv; + smb_lgrp_is_member; + smb_lgrp_iterate; + smb_lgrp_iterclose; + smb_lgrp_iteropen; + smb_lgrp_numbydomain; + smb_lgrp_numbymember; + smb_lgrp_rename; + smb_lgrp_setcmnt; + smb_lgrp_setpriv; + smb_lgrp_start; + smb_lgrp_stop; + smb_lgrp_strerror; smb_load_kconfig; + smb_lookup_name; + smb_lookup_sid; smb_mac_chk; smb_mac_dec_seqnum; smb_mac_inc_seqnum; @@ -245,37 +241,25 @@ SUNWprivate { smb_privset_free; smb_privset_init; smb_privset_log; + smb_privset_merge; smb_privset_new; smb_privset_query; smb_privset_size; smb_privset_validate; - smb_purge_domain_info; smb_trace; smb_tracef; - xdr_ntgrp_dr_arg_t; - xdr_ntgrp_list_t; - xdr_ntgrp_member_list_t; - xdr_ntpriv_list_t; smb_pwd_getpasswd; smb_pwd_setcntl; smb_pwd_setpasswd; - smb_set_domain_member; - smb_set_machine_pwd; + smb_resolve_fqdn; + smb_resolve_netbiosname; smb_setdomaininfo; - smb_smf_create_instance_pgroup; smb_smf_create_service_pgroup; - smb_smf_delete_instance_pgroup; - smb_smf_delete_property; - smb_smf_delete_service_pgroup; smb_smf_end_transaction; smb_smf_get_boolean_property; smb_smf_get_integer_property; - smb_smf_get_iterator; smb_smf_get_opaque_property; smb_smf_get_string_property; - smb_smf_instance_create; - smb_smf_instance_delete; - smb_smf_instance_exists; smb_smf_scf_fini; smb_smf_scf_init; smb_smf_set_boolean_property; @@ -313,10 +297,6 @@ SUNWprivate { utf8_strlwr; utf8_strncasecmp; utf8_strupr; - xdr_ntgrp_dr_arg_t; - xdr_ntgrp_list_t; - xdr_ntgrp_member_list_t; - xdr_ntpriv_list_t; xdr_smb_dr_bytes_t; xdr_smb_dr_string_t; xdr_smb_dr_ulist_t; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c index 4a84b5d462..79a512be2d 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_api_door_calls.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -47,20 +47,8 @@ char *smbapi_desc[] = { "", "", "SmbapiUserList", - "SmbGroupAdd", - "SmbGroupDelete", - "SmbGroupAddMember", - "SmbGroupRemoveMember", - "SmbGroupGetCount", - "SmbGroupGetCacheSize", - "SmbGroupModify", - "SmbGroupPresentablePrivNum", - "SmbGroupPresentablePriv", - "SmbGroupGetPriv", - "SmbGroupSetPriv", - "SmbGroupListGroups", - "SmbGroupListMembers", - "SmbGroupMembersCount", + "SmbLookupSid", + "SmbLookupName", 0 }; @@ -104,535 +92,48 @@ smb_api_ulist(int offset, smb_dr_ulist_t *users) return (rc); } -/* Routines for SMB Group Door Client APIs */ -uint32_t -smb_group_add(char *gname, char *desc) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_ADD; - int fd; - - if ((gname == 0) || (*gname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->desc = desc; - if ((buf = smb_dr_encode_common(opcode, args, - xdr_ntgrp_dr_arg_t, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_delete(char *gname) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_DELETE; - int fd; - - if ((gname == 0) || (*gname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((buf = smb_dr_encode_string(opcode, gname, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_add(char *gname, char *member) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_ADD; - int fd; - - if ((gname == 0) || (*gname == 0) || - (member == 0) || (*member == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->member = member; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_remove(char *gname, char *member) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_REMOVE; - int fd; - - if ((gname == 0) || (*gname == 0) || - (member == 0) || (*member == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->member = member; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - - -uint32_t -smb_group_count(int *cnt) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - uint_t opcode = SMB_DR_GROUP_COUNT; - int fd; - - if (cnt == 0) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - *cnt = 0; - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, cnt) != 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_cachesize(int *sz) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - uint_t opcode = SMB_DR_GROUP_CACHE_SIZE; - int fd; - - if (sz == 0) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - *sz = 0; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, sz) != 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_modify(char *gname, char *newgname, char *desc) -{ - ntgrp_dr_arg_t *args; - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MODIFY; - int fd; - - if ((gname == 0) || (*gname == 0) || - (newgname == 0) || (*newgname == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); - } - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->desc = desc; - args->newgname = newgname; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_num(int *num) +int +smb_lookup_sid(nt_sid_t *sid, char *sidbuf, int sidbuflen) { char *buf, *rbufp; size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_NUM; + int opcode = SMB_DR_LOOKUP_SID; + char strsid[NT_SID_FMTBUF_SIZE]; + char *name = NULL; int fd; - if (num == 0) { + if ((sidbuf == NULL) || (sidbuflen == 0)) { syslog(LOG_ERR, "%s: invalid parameter(s)", smbapi_desc[opcode]); return (NT_STATUS_INVALID_PARAMETER); } - *num = 0; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, num) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_list(ntpriv_list_t **list) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_LIST; - int fd; - *list = NULL; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, - smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - if ((buf = smb_dr_set_opcode(opcode, &buflen)) == 0) { - (void) close(fd); - return (NT_STATUS_INVALID_PARAMETER); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result */ - if (rbufp) { - if ((*list = smb_dr_decode_grp_privlist( - rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_get(char *gname, uint32_t privid, uint32_t *privval) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_GET; - int fd; - uint32_t retval; - - *privval = SE_PRIVILEGE_DISABLED; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", + if (!nt_sid_is_valid(sid)) { + syslog(LOG_ERR, "%s: invalid SID", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); + return (NT_STATUS_INVALID_SID); } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->privid = privid; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, - &retval) != 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - *privval = retval; - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_priv_set(char *gname, uint32_t privid, uint32_t priv_attr) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_PRIV_SET; - int fd; if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) return (NT_STATUS_INTERNAL_ERROR); /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->privid = privid; - args->priv_attr = priv_attr; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { + nt_sid_format2(sid, strsid); + if ((buf = smb_dr_encode_string(opcode, strsid, &buflen)) == 0) { syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - free(args); rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, smbapi_desc[opcode]); /* Decode Result. */ if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_uint32_t, &rc) != 0) { + name = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET, + rbufsize - SMB_DR_DATA_OFFSET); + if (name == NULL) { + smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } @@ -640,73 +141,26 @@ smb_group_priv_set(char *gname, uint32_t privid, uint32_t priv_attr) smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); - return (rc); -} -uint32_t -smb_group_list(int offset, ntgrp_list_t **list, char *scope, int type) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_LIST; - int fd; - *list = NULL; - - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); + if ((name == NULL) || (*name == '\0')) + nt_sid_format2(sid, sidbuf); - /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->offset = offset; - args->type = type; - args->scope = scope; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - free(args); - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if (rbufp) { - if ((*list = smb_dr_decode_grp_list(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); + (void) strlcpy(sidbuf, name, sidbuflen); + xdr_free(xdr_string, (char *)&name); + return (NT_STATUS_SUCCESS); } -uint32_t -smb_group_member_list(char *gname, int offset, ntgrp_member_list_t **members) +int +smb_lookup_name(char *name, smb_gsid_t *sid) { char *buf, *rbufp; size_t buflen, rbufsize; - ntgrp_dr_arg_t *args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_LIST; + int opcode = SMB_DR_LOOKUP_NAME; + char *strsid = NULL; + char *p; int fd; - *members = NULL; - if ((gname == 0) || (*gname == 0)) { + if ((name == NULL) || (*name == '\0')) { syslog(LOG_ERR, "%s: invalid parameter(s)", smbapi_desc[opcode]); return (NT_STATUS_INVALID_PARAMETER); @@ -716,149 +170,38 @@ smb_group_member_list(char *gname, int offset, ntgrp_member_list_t **members) return (NT_STATUS_INTERNAL_ERROR); /* Encode */ - if ((args = (ntgrp_dr_arg_t *)malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory for ret_mem_list", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(args, sizeof (ntgrp_dr_arg_t)); - args->gname = gname; - args->offset = offset; - if ((buf = smb_dr_encode_common(opcode, args, xdr_ntgrp_dr_arg_t, - &buflen)) == 0) { + if ((buf = smb_dr_encode_string(opcode, name, &buflen)) == 0) { syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - free(args); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - free(args); rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, smbapi_desc[opcode]); /* Decode Result. */ if (rbufp) { - if ((*members = smb_dr_decode_grp_memberlist( - rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET)) == 0) { + strsid = smb_dr_decode_string(rbufp + SMB_DR_DATA_OFFSET, + rbufsize - SMB_DR_DATA_OFFSET); + if (strsid == NULL) { + smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); (void) close(fd); return (NT_STATUS_INTERNAL_ERROR); } - rc = NT_STATUS_SUCCESS; - } - - smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - (void) close(fd); - return (rc); -} - -uint32_t -smb_group_member_count(char *gname, int *cnt) -{ - char *buf, *rbufp; - size_t buflen, rbufsize; - ntgrp_dr_arg_t *dec_args; - uint32_t rc = NT_STATUS_UNSUCCESSFUL; - int opcode = SMB_DR_GROUP_MEMBER_COUNT; - int fd; - - if ((gname == 0) || (*gname == 0) || (cnt == 0)) { - syslog(LOG_ERR, "%s: invalid parameter(s)", - smbapi_desc[opcode]); - return (NT_STATUS_INVALID_PARAMETER); } - if (smb_dr_clnt_open(&fd, SMB_DR_SVC_NAME, smbapi_desc[opcode]) == -1) - return (NT_STATUS_INTERNAL_ERROR); - - /* Encode */ - if ((buf = smb_dr_encode_string(opcode, gname, &buflen)) == 0) { - syslog(LOG_ERR, "%s: Encode error", smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_INTERNAL_ERROR); - } - - rbufp = smb_dr_clnt_call(fd, buf, buflen, &rbufsize, - smbapi_desc[opcode]); - - /* Decode Result. */ - if ((dec_args = (ntgrp_dr_arg_t *) - malloc(sizeof (ntgrp_dr_arg_t))) == 0) { - syslog(LOG_ERR, "%s: cannot allocate memory", - smbapi_desc[opcode]); - (void) close(fd); - return (NT_STATUS_NO_MEMORY); - } - bzero(dec_args, sizeof (ntgrp_dr_arg_t)); - if (rbufp) { - if (smb_dr_decode_common(rbufp + SMB_DR_DATA_OFFSET, - rbufsize - SMB_DR_DATA_OFFSET, xdr_ntgrp_dr_arg_t, dec_args) - != 0) { - free(dec_args); - (void) close(fd); - return (dec_args->ntstatus); - } - } - *cnt = dec_args->count; - rc = dec_args->ntstatus; smb_dr_clnt_free(buf, buflen, rbufp, rbufsize); - free(dec_args); (void) close(fd); - return (rc); -} -/* Helper functions for local group door service to free up data structures */ -void -smb_group_free_privlist(ntpriv_list_t *list, int deletelist) -{ - int i; - if (!list) - return; - if (list->privs != NULL) { - for (i = 0; i < list->cnt; i++) { - if (list->privs[i] != NULL) { - free(list->privs[i]->name); - free(list->privs[i]); - } - } - if (deletelist) - free(list); + p = strchr(strsid, '-'); + if (p == NULL) { + xdr_free(xdr_string, (char *)&strsid); + return (NT_STATUS_NONE_MAPPED); } -} -void -smb_group_free_list(ntgrp_list_t *list, int entries_only) -{ - int i; - - if (!list) { - return; - } - - for (i = 0; i < list->cnt; i++) { - free(list->groups[i].name); - free(list->groups[i].desc); - free(list->groups[i].type); - free(list->groups[i].sid); - } - if (!entries_only) - free(list); -} - -void -smb_group_free_memberlist(ntgrp_member_list_t *members, - int entries_only) -{ - int i; - - if (!members) { - return; - } - - for (i = 0; i < members->cnt; i++) { - free(members->members[i]); - } - if (!entries_only) - free(members); + *p++ = '\0'; + sid->gs_type = atoi(strsid); + sid->gs_sid = nt_sid_strtosid(p); + xdr_free(xdr_string, (char *)&strsid); + return (NT_STATUS_SUCCESS); } diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c index d8950616db..ccd33ca1af 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_auth.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_auth.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -303,7 +303,6 @@ smb_auth_ntlmv2_hash(unsigned char *ntlm_hash, return (SMBAUTH_FAILURE); (void) utf8_strupr(username); - (void) utf8_strupr(ntdomain); data_len = strlen(username) + strlen(ntdomain); buf = (unsigned char *)malloc((data_len + 1) * sizeof (char)); @@ -397,6 +396,7 @@ smb_auth_set_info(char *username, unsigned short blob_len; unsigned char blob_buf[SMBAUTH_BLOB_MAXLEN]; int rc; + char *uppercase_dom; auth->lmcompatibility_lvl = lmcomp_lvl; if (lmcomp_lvl == 2) { @@ -421,12 +421,23 @@ smb_auth_set_info(char *username, (void) memcpy(auth->hash, ntlm_hash, SMBAUTH_HASH_SZ); } + if (!domain) + return (-1); + + if ((uppercase_dom = strdup(domain)) == NULL) + return (-1); + + (void) utf8_strupr(uppercase_dom); + if (smb_auth_ntlmv2_hash(auth->hash, username, - domain, auth->hash_v2) != SMBAUTH_SUCCESS) + uppercase_dom, auth->hash_v2) != SMBAUTH_SUCCESS) { + free(uppercase_dom); return (-1); + } /* generate data blob */ - smb_auth_gen_data_blob(&auth->data_blob, domain); + smb_auth_gen_data_blob(&auth->data_blob, uppercase_dom); + free(uppercase_dom); blob_len = smb_auth_blob_to_string(&auth->data_blob, blob_buf); /* generate NTLMv2 response */ @@ -538,67 +549,90 @@ smb_ntlmv2_password_ok( unsigned char *ntlm_hash, unsigned char *passwd, int pwdlen, + char *domain, char *username) { unsigned char *clnt_blob; int clnt_blob_len; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char *ntlmv2_resp; - boolean_t ok; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_blob_len = pwdlen - SMBAUTH_HASH_SZ; clnt_blob = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" * - * * The NTLMv2 Hash is created from: + * The NTLMv2 Hash is created from: * - NTLM hash * - user's username, and * - the name of the logon destination(i.e. the NetBIOS name of either - * the SMB server or NT Domain against which the suer is trying to + * the SMB server or NT Domain against which the user is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using NTLMv2 challenge / response. - * The NTLMv2 hash is actually created with the destination info="" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } ntlmv2_resp = (unsigned char *)malloc(SMBAUTH_HASH_SZ + clnt_blob_len); - if (ntlmv2_resp == NULL) - return (B_FALSE); - - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) { - free(ntlmv2_resp); + if (ntlmv2_resp == NULL) { + free(dest[1]); return (B_FALSE); } - ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_blob, clnt_blob_len, ntlmv2_resp) < 0) + break; + + ok = (bcmp(passwd, ntlmv2_resp, pwdlen) == 0); + if (ok == B_TRUE) + break; + } + + free(dest[1]); free(ntlmv2_resp); return (ok); } -static int +static boolean_t smb_lmv2_password_ok( unsigned char *challenge, uint32_t clen, unsigned char *ntlm_hash, unsigned char *passwd, + char *domain, char *username) { unsigned char *clnt_challenge; unsigned char ntlmv2_hash[SMBAUTH_HASH_SZ]; unsigned char lmv2_resp[SMBAUTH_LM_RESP_SZ]; + boolean_t ok = B_FALSE; + char *dest[3]; + int i; clnt_challenge = &passwd[SMBAUTH_HASH_SZ]; + dest[0] = domain; + if ((dest[1] = strdup(domain)) == NULL) + return (B_FALSE); + (void) utf8_strupr(dest[1]); + dest[2] = ""; /* * 15.5.2 The NTLMv2 Password Hash, pg. 279, of the "Implementing CIFS" @@ -610,23 +644,31 @@ smb_lmv2_password_ok( * the SMB server or NT Domain against which the suer is trying to * authenticate. * - * (N.L.) With my experience, this is not exactly true. It's really - * tricky how the NTLMv2 hash is generated by the Windows client when - * logging into a standalone server using LMv2 challenge/response. - * The NTLMv2 hash is actually created with the destination info = "" - * as opposed to the SMB server name mentioned in the book. + * Experiments show this is not exactly the case. + * For Windows Server 2003, the domain name needs to be included and + * converted to uppercase. For Vista, the domain name needs to be + * included also, but leave the case alone. And in some cases it needs + * to be empty. All three variants are tried here. */ - if (smb_auth_ntlmv2_hash(ntlm_hash, username, "", ntlmv2_hash) != - SMBAUTH_SUCCESS) { - return (B_FALSE); - } - if (smb_auth_v2_response(ntlmv2_hash, challenge, - clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, - lmv2_resp) < 0) { - return (B_FALSE); + + for (i = 0; i < (sizeof (dest) / sizeof (char *)); i++) { + if (smb_auth_ntlmv2_hash(ntlm_hash, username, dest[i], + ntlmv2_hash) != SMBAUTH_SUCCESS) + break; + + if (smb_auth_v2_response(ntlmv2_hash, challenge, + clen, clnt_challenge, SMBAUTH_V2_CLNT_CHALLENGE_SZ, + lmv2_resp) < 0) + break; + + ok = (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + if (ok == B_TRUE) + break; + } - return (bcmp(passwd, lmv2_resp, SMBAUTH_LM_RESP_SZ) == 0); + free(dest[1]); + return (ok); } /* @@ -644,17 +686,17 @@ smb_auth_validate_lm( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; boolean_t ok = B_FALSE; + int64_t lmlevel; if (pwdlen != SMBAUTH_LM_RESP_SZ) return (B_FALSE); - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if (lmlevel <= 3) { ok = smb_lm_password_ok(challenge, clen, smbpw->pw_lmhash, @@ -663,7 +705,7 @@ smb_auth_validate_lm( if (!ok) ok = smb_lmv2_password_ok(challenge, clen, smbpw->pw_nthash, - passwd, username); + passwd, domain, username); return (ok); } @@ -683,21 +725,21 @@ smb_auth_validate_nt( smb_passwd_t *smbpw, unsigned char *passwd, int pwdlen, + char *domain, char *username) { - int lmlevel; + int64_t lmlevel; boolean_t ok; - smb_config_rdlock(); - lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lmlevel) != SMBD_SMF_OK) + return (B_FALSE); if ((lmlevel == 5) && (pwdlen <= SMBAUTH_LM_RESP_SZ)) return (B_FALSE); if (pwdlen > SMBAUTH_LM_RESP_SZ) ok = smb_ntlmv2_password_ok(challenge, clen, - smbpw->pw_nthash, passwd, pwdlen, username); + smbpw->pw_nthash, passwd, pwdlen, domain, username); else ok = smb_ntlm_password_ok(challenge, clen, smbpw->pw_nthash, passwd); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c index 84d95609e5..f5e6bb8a48 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,27 +40,20 @@ #include <ctype.h> #include <sys/types.h> #include <libscf.h> +#include <assert.h> #include <smbsrv/libsmb.h> typedef struct smb_cfg_param { - char *sc_pg; + smb_cfg_id_t sc_id; char *sc_name; int sc_type; - char *sc_value; uint32_t sc_flags; } smb_cfg_param_t; /* * config parameter flags */ -#define SMB_CF_NOTINIT 0x00 /* Not initialized yet */ -#define SMB_CF_DEFINED 0x01 /* Defined/read from env */ -#define SMB_CF_MODIFIED 0x02 /* Has been modified */ -#define SMB_CF_SYSTEM 0x04 /* system; not part of cifs config */ - -#define SMB_CL_NONE 0 -#define SMB_CL_READ 1 -#define SMB_CL_WRITE 2 +#define SMB_CF_PROTECTED 0x01 /* idmap SMF fmri and Property Group */ #define IDMAP_FMRI_PREFIX "system/idmap" @@ -77,115 +70,79 @@ typedef struct smb_cfg_param { static char *b64_data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static rwlock_t smb_cfg_rwlk; -static int lock_type = SMB_CL_NONE; - -/* - * IMPORTANT: any changes to the order of this table's entries - * need to be reflected in smb_cfg_id_t enum in libsmb.h - */ static smb_cfg_param_t smb_cfg_table[] = { - /* Redirector configuration, User space */ - {SMBD_PG_NAME, SMB_CD_RDR_IPCMODE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCUSER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_RDR_IPCPWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - /* Oplock configuration, Kernel Only */ - {SMBD_PG_NAME, SMB_CD_OPLOCK_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_OPLOCK_TIMEOUT, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, + {SMB_CI_OPLOCK_ENABLE, "oplock_enable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_OPLOCK_TIMEOUT, "oplock_timeout", SCF_TYPE_INTEGER, 0}, /* Autohome configuration */ - {SMBD_PG_NAME, SMB_CD_AUTOHOME_MAP, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_AUTOHOME_MAP, "autohome_map", SCF_TYPE_ASTRING, 0}, /* Domain/PDC configuration */ - {SMBD_PG_NAME, SMB_CD_DOMAIN_SID, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_MEMB, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_NAME, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DOMAIN_SRV, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_DOMAIN_SID, "domain_sid", SCF_TYPE_ASTRING, 0}, + {SMB_CI_DOMAIN_MEMB, "domain_member", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_DOMAIN_NAME, "domain_name", SCF_TYPE_ASTRING, 0}, + {SMB_CI_DOMAIN_SRV, "pdc", SCF_TYPE_ASTRING, 0}, /* WINS configuration */ - {SMBD_PG_NAME, SMB_CD_WINS_SRV1, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_WINS_SRV2, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_WINS_EXCL, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, + {SMB_CI_WINS_SRV1, "wins_server_1", SCF_TYPE_ASTRING, 0}, + {SMB_CI_WINS_SRV2, "wins_server_2", SCF_TYPE_ASTRING, 0}, + {SMB_CI_WINS_EXCL, "wins_exclude", SCF_TYPE_ASTRING, 0}, /* RPC services configuration */ - {SMBD_PG_NAME, SMB_CD_SRVSVC_SHRSET_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_LOGR_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MLRPC_KALIVE, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, + {SMB_CI_SRVSVC_SHRSET_ENABLE, "srvsvc_sharesetinfo_enable", + SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_MLRPC_KALIVE, "mlrpc_keep_alive_interval", + SCF_TYPE_INTEGER, 0}, /* Kmod specific configuration */ - {SMBD_PG_NAME, SMB_CD_MAX_BUFSIZE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MAX_WORKERS, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MAX_CONNECTIONS, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_KEEPALIVE, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_RESTRICT_ANON, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - - {SMBD_PG_NAME, SMB_CD_SIGNING_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SIGNING_REQD, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SIGNING_CHECK, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_MAX_BUFSIZE, "max_bufsize", SCF_TYPE_INTEGER, 0}, + {SMB_CI_MAX_WORKERS, "max_workers", SCF_TYPE_INTEGER, 0}, + {SMB_CI_MAX_CONNECTIONS, "max_connections", SCF_TYPE_INTEGER, 0}, + {SMB_CI_KEEPALIVE, "keep_alive", SCF_TYPE_INTEGER, 0}, + {SMB_CI_RESTRICT_ANON, "restrict_anonymous", SCF_TYPE_BOOLEAN, 0}, + + {SMB_CI_SIGNING_ENABLE, "signing_enabled", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SIGNING_REQD, "signing_required", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SIGNING_CHECK, "signing_check", SCF_TYPE_BOOLEAN, 0}, /* Kmod tuning configuration */ - {SMBD_PG_NAME, SMB_CD_FLUSH_REQUIRED, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SYNC_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DIRSYMLINK_DISABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ANNONCE_QUOTA, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_FLUSH_REQUIRED, "flush_required", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_SYNC_ENABLE, "sync_enable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_DIRSYMLINK_DISABLE, "dir_symlink_disable", SCF_TYPE_BOOLEAN, 0}, + {SMB_CI_ANNONCE_QUOTA, "announce_quota", SCF_TYPE_BOOLEAN, 0}, /* SMBd configuration */ - {SMBD_PG_NAME, SMB_CD_SECURITY, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_NBSCOPE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_SYS_CMNT, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_LM_LEVEL, SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_MSDCS_DISABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_SECURITY, "security", SCF_TYPE_ASTRING, 0}, + {SMB_CI_NBSCOPE, "netbios_scope", SCF_TYPE_ASTRING, 0}, + {SMB_CI_SYS_CMNT, "system_comment", SCF_TYPE_ASTRING, 0}, + {SMB_CI_LM_LEVEL, "lmauth_level", SCF_TYPE_INTEGER, 0}, /* ADS Configuration */ - {SMBD_PG_NAME, SMB_CD_ADS_ENABLE, SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_USER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PROTECTED_PG_NAME, SMB_CD_ADS_PASSWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_DOMAIN, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_USER_CONTAINER, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_SITE, SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_ADS_IPLOOKUP, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, + {SMB_CI_ADS_SITE, "ads_site", SCF_TYPE_ASTRING, 0}, /* Dynamic DNS */ - {SMBD_PG_NAME, SMB_CD_DYNDNS_ENABLE, - SCF_TYPE_BOOLEAN, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_COUNT, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - {SMBD_PG_NAME, SMB_CD_DYNDNS_RETRY_SEC, - SCF_TYPE_INTEGER, 0, SMB_CF_NOTINIT}, - - {SMBD_PROTECTED_PG_NAME, SMB_CD_MACHINE_PASSWD, - SCF_TYPE_ASTRING, 0, SMB_CF_NOTINIT} + {SMB_CI_DYNDNS_ENABLE, "ddns_enable", SCF_TYPE_BOOLEAN, 0}, + + {SMB_CI_MACHINE_PASSWD, "machine_passwd", SCF_TYPE_ASTRING, + SMB_CF_PROTECTED} /* SMB_CI_MAX */ }; +static smb_cfg_param_t *smb_config_getent(smb_cfg_id_t); + static boolean_t smb_is_base64(unsigned char c); static char *smb_base64_encode(char *str_to_encode); static char *smb_base64_decode(char *encoded_str); -static int smb_config_update(smb_cfg_param_t *cfg, char *value); -static int smb_config_save_all(); -static int smb_config_save(char *pgname); + +char * +smb_config_getname(smb_cfg_id_t id) +{ + smb_cfg_param_t *cfg; + cfg = smb_config_getent(id); + return (cfg->sc_name); +} static boolean_t smb_is_base64(unsigned char c) @@ -321,105 +278,6 @@ smb_base64_decode(char *encoded_str) return (ret); } -/* - * Basically commit the transaction. - */ -static int -smb_config_saveenv(smb_scfhandle_t *handle) -{ - int ret = 0; - - ret = smb_smf_end_transaction(handle); - - smb_smf_scf_fini(handle); - return (ret); -} - -/* - * smb_config_getenv - * - * Get the property value from SMF. - */ -char * -smb_config_getenv(smb_cfg_id_t id) -{ - smb_scfhandle_t *handle; - char *value; - - if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) - return (NULL); - - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - free(value); - return (NULL); - } - - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - - if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, value, - sizeof (char) * MAX_VALUE_BUFLEN) != 0) { - smb_smf_scf_fini(handle); - free(value); - return (NULL); - } - - smb_smf_scf_fini(handle); - return (value); -} - -/* - * smb_config_getenv_dec - * - * For protected property, the value obtained from SMF will be decoded. - * The decoded property value will be returned. - * - * This function should only be called by smb_config_load to populate - * the SMB config cache. - */ -static char * -smb_config_getenv_dec(smb_cfg_id_t id) -{ - smb_scfhandle_t *handle; - char *value; - char *dec; - - if ((value = malloc(MAX_VALUE_BUFLEN * sizeof (char))) == NULL) - return (NULL); - - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - free(value); - return (NULL); - } - - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - - if (smb_smf_get_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, value, - sizeof (char) * MAX_VALUE_BUFLEN) != 0) { - smb_smf_scf_fini(handle); - free(value); - return (NULL); - } - smb_smf_scf_fini(handle); - if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME)) - return (value); - - if (!value) - return (NULL); - - if (*value == '\0') { - free(value); - return (NULL); - } - - dec = smb_base64_decode(value); - free(value); - return (dec); -} - static char * smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) { @@ -449,7 +307,7 @@ smb_config_getenv_generic(char *name, char *svc_fmri_prefix, char *svc_propgrp) } -int +static int smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, char *name, char *value) { @@ -480,495 +338,302 @@ smb_config_setenv_generic(char *svc_fmri_prefix, char *svc_propgrp, } /* - * smb_config_setenv + * smb_config_getstr * - * For protected properties, the value will be encoded using base64 - * algorithm. The encoded string will be stored in SMF. + * Fetch the specified string configuration item from SMF */ int -smb_config_setenv(smb_cfg_id_t id, char *value) +smb_config_getstr(smb_cfg_id_t id, char *cbuf, int bufsz) { - smb_scfhandle_t *handle = NULL; - char *enc = NULL; - int is_protected = 0; + smb_scfhandle_t *handle; + smb_cfg_param_t *cfg; + int rc = SMBD_SMF_OK; - if ((id >= SMB_CI_MAX) || (id < 0)) { - return (1); - } + *cbuf = '\0'; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_ASTRING); handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - return (1); - } + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); + if (cfg->sc_flags & SMB_CF_PROTECTED) { + char protbuf[SMB_ENC_LEN]; + char *tmp; - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (1); - } + if ((rc = smb_smf_create_service_pgroup(handle, + SMBD_PROTECTED_PG_NAME)) != SMBD_SMF_OK) + goto error; - if (strcmp(smb_cfg_table[id].sc_pg, SMBD_PROTECTED_PG_NAME) == 0) { - if ((value == NULL) || (*value == '\0')) { - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); - } + if ((rc = smb_smf_get_string_property(handle, cfg->sc_name, + protbuf, sizeof (protbuf))) != SMBD_SMF_OK) + goto error; - if ((enc = smb_base64_encode(value)) == NULL) { - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); + if (*protbuf != '\0') { + tmp = smb_base64_decode(protbuf); + (void) strlcpy(cbuf, tmp, bufsz); + free(tmp); } - - is_protected = 1; - } - - if (smb_smf_set_property(handle, smb_cfg_table[id].sc_type, - smb_cfg_table[id].sc_name, is_protected ? enc : value) - != SMBD_SMF_OK) { - if (enc) - free(enc); - (void) smb_smf_end_transaction(handle); - smb_smf_scf_fini(handle); - return (1); - } - - if (enc) - free(enc); - - if (smb_smf_end_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (1); + } else { + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_string_property(handle, cfg->sc_name, + cbuf, bufsz); } +error: smb_smf_scf_fini(handle); - return (0); -} - -static void -smb_config_setenv_trans(smb_scfhandle_t *handle, int type, - char *name, char *value) -{ - if (smb_smf_set_property(handle, type, name, value) != SMBD_SMF_OK) { - syslog(LOG_ERR, "Failed to save service property %s", name); - } + return (rc); } /* - * smb_config_setenv_trans_protected + * smb_config_getnum * - * This function should only be called to set protected properties - * in SMF. The argument 'value' will be encoded using base64 algorithm. - * The encoded string will be stored in SMF. + * Returns the value of a numeric config param. */ -static void -smb_config_setenv_trans_protected(smb_scfhandle_t *handle, char *name, - char *value) -{ - char *enc; - - if ((value == NULL) || (*value == '\0')) - return; - - if ((enc = smb_base64_encode(value)) == NULL) - return; - - if (smb_smf_set_string_property(handle, name, enc) != SMBD_SMF_OK) { - syslog(LOG_ERR, "Failed to save service protected property" - " %s", name); - } - - free(enc); -} - int -smb_config_unsetenv(smb_cfg_id_t id) +smb_config_getnum(smb_cfg_id_t id, int64_t *cint) { - smb_scfhandle_t *handle = NULL; - int ret = 1; + smb_scfhandle_t *handle; + smb_cfg_param_t *cfg; + int rc = SMBD_SMF_OK; - handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - return (ret); - } + *cint = 0; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_INTEGER); - (void) smb_smf_create_service_pgroup(handle, smb_cfg_table[id].sc_pg); - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - smb_smf_scf_fini(handle); - return (ret); - } - ret = smb_smf_delete_property(handle, smb_cfg_table[id].sc_name); - (void) smb_smf_end_transaction(handle); + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_integer_property(handle, cfg->sc_name, cint); smb_smf_scf_fini(handle); - return (ret); -} -static int -smb_config_unsetenv_trans(smb_scfhandle_t *handle, char *name) -{ - return (smb_smf_delete_property(handle, name)); + return (rc); } /* - * smb_config_load + * smb_config_getbool * - * Loads all the CIFS configuration parameters and sets up the - * config table. + * Returns the value of a boolean config param. */ -int -smb_config_load() +boolean_t +smb_config_getbool(smb_cfg_id_t id) { - smb_cfg_id_t id; + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char *value; + int rc = SMBD_SMF_OK; + uint8_t vbool; - (void) rw_rdlock(&smb_cfg_rwlk); - for (id = 0; id < SMB_CI_MAX; id++) { - value = smb_config_getenv_dec(id); - cfg = &smb_cfg_table[id]; - /* - * enval == 0 could mean two things, either the - * config param is not defined, or it has been - * removed. If the variable has already been defined - * and now enval is 0, it should be removed, otherwise - * we don't need to do anything in this case. - */ - if ((cfg->sc_flags & SMB_CF_DEFINED) || value) { - if (smb_config_update(cfg, value) != 0) { - (void) rw_unlock(&smb_cfg_rwlk); - if (value) - free(value); - return (1); - } - } - if (value) { - free(value); - } - } + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_BOOLEAN); - (void) rw_unlock(&smb_cfg_rwlk); + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (B_FALSE); + + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_get_boolean_property(handle, cfg->sc_name, &vbool); + smb_smf_scf_fini(handle); - return (0); + return ((rc == SMBD_SMF_OK) ? (vbool == 1) : B_FALSE); } /* * smb_config_get * - * Returns value of the specified config param. - * The return value is a string pointer to the locally - * allocated memory if the config param is defined - * otherwise it would be NULL. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. Caller MUST NOT modify the returned buffer directly. + * This function returns the value of the requested config + * iterm regardless of its type in string format. This should + * be used when the config item type is not known by the caller. */ -char * -smb_config_get(smb_cfg_id_t id) +int +smb_config_get(smb_cfg_id_t id, char *cbuf, int bufsz) { - if (id < SMB_CI_MAX) - return (smb_cfg_table[id].sc_value); + smb_cfg_param_t *cfg; + int64_t cint; + int rc; - return (0); -} + cfg = smb_config_getent(id); + switch (cfg->sc_type) { + case SCF_TYPE_ASTRING: + return (smb_config_getstr(id, cbuf, bufsz)); -/* - * smb_config_getstr - * - * Returns value of the specified config param. - * The returned pointer never will be NULL if the given - * 'id' is valid. If the config param is not defined its - * default value will be returned. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. Caller MUST NOT modify the returned buffer directly. - */ -char * -smb_config_getstr(smb_cfg_id_t id) -{ - smb_cfg_param_t *cfg; + case SCF_TYPE_INTEGER: + rc = smb_config_getnum(id, &cint); + if (rc == SMBD_SMF_OK) + (void) snprintf(cbuf, bufsz, "%lld", cint); + return (rc); - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - if (cfg->sc_value) - return (cfg->sc_value); + case SCF_TYPE_BOOLEAN: + if (smb_config_getbool(id)) + (void) strlcpy(cbuf, "true", bufsz); + else + (void) strlcpy(cbuf, "false", bufsz); + return (SMBD_SMF_OK); } - return (NULL); + return (SMBD_SMF_INVALID_ARG); } /* - * smb_config_getnum + * smb_config_setstr * - * Returns the value of a numeric config param. - * If the config param is not defined it'll return the - * default value. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. + * Set the specified config param with the given + * value. */ -uint32_t -smb_config_getnum(smb_cfg_id_t id) +int +smb_config_setstr(smb_cfg_id_t id, char *value) { + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char *strval = NULL; + int rc = SMBD_SMF_OK; + boolean_t protected; + char *tmp = NULL; + char *pg; - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - if (cfg->sc_value) - strval = cfg->sc_value; + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_ASTRING); - if (strval) - return (strtol(strval, 0, 10)); + if (cfg->sc_flags & SMB_CF_PROTECTED) { + pg = SMBD_PROTECTED_PG_NAME; + protected = B_TRUE; + } else { + pg = SMBD_PG_NAME; + protected = B_FALSE; } - return (0); -} + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); -/* - * smb_config_getyorn - * - * Returns the value of a yes/no config param. - * Returns 1 is config is set to "yes", otherwise 0. - * - * This function MUST be called after a smb_config_rd/wrlock - * function. - */ -int -smb_config_getyorn(smb_cfg_id_t id) -{ - char *val; + rc = smb_smf_create_service_pgroup(handle, pg); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - val = smb_config_get(id); - if (val) { - if (strcasecmp(val, "true") == 0) - return (1); + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); + return (rc); } - return (0); -} - -/* - * smb_config_set - * - * Set/update the specified config param with the given - * value. If the value is NULL the config param will be - * unset as if it is not defined. - * - * This function MUST be called after a smb_config_wrlock - * function. - */ -int -smb_config_set(smb_cfg_id_t id, char *value) -{ - smb_cfg_param_t *cfg; - int rc = 0; + if (protected && value && (*value != '\0')) { + if ((tmp = smb_base64_encode(value)) == NULL) { + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (SMBD_SMF_NO_MEMORY); + } - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - rc = smb_config_update(cfg, value); - if (rc == 0) - cfg->sc_flags |= SMB_CF_MODIFIED; - return (rc); + value = tmp; } - return (1); + rc = smb_smf_set_string_property(handle, cfg->sc_name, value); + + free(tmp); + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* * smb_config_setnum * - * Set/update the specified config param with the given - * value. This is used for numeric config params. The given - * number will be converted to string before setting the - * config param. - * - * This function MUST be called after a smb_config_wrlock - * function. + * Sets a numeric configuration iterm */ int -smb_config_setnum(smb_cfg_id_t id, uint32_t num) +smb_config_setnum(smb_cfg_id_t id, int64_t value) { + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - char value[32]; - int rc = 0; + int rc = SMBD_SMF_OK; - if (id < SMB_CI_MAX) { - cfg = &smb_cfg_table[id]; - (void) snprintf(value, sizeof (value), "%u", num); - rc = smb_config_update(cfg, value); - if (rc == 0) - cfg->sc_flags |= SMB_CF_MODIFIED; - return (rc); - } - - return (1); -} + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_INTEGER); -/* - * smb_config_rdlock - * - * Lock the config table for read access. - * This function MUST be called before any kind of - * read access to the config table i.e. all flavors of - * smb_config_get function - */ -void -smb_config_rdlock() -{ - (void) rw_rdlock(&smb_cfg_rwlk); - lock_type = SMB_CL_READ; -} - -/* - * smb_config_wrlock - * - * Lock the config table for write access. - * This function MUST be called before any kind of - * write access to the config table i.e. all flavors of - * smb_config_set function - */ -void -smb_config_wrlock() -{ - (void) rw_wrlock(&smb_cfg_rwlk); - lock_type = SMB_CL_WRITE; -} - -/* - * smb_config_wrlock - * - * Unlock the config table. - * If the config table has been locked for write access - * smb_config_save_all() will be called to save the changes - * before unlocking the table. - * - * This function MUST be called after smb_config_rd/wrlock - */ -void -smb_config_unlock() -{ - if (lock_type == SMB_CL_WRITE) - (void) smb_config_save_all(); - (void) rw_unlock(&smb_cfg_rwlk); -} + handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); -/* - * smb_config_save_all - * - * Save all modified parameters to SMF. - */ -static int -smb_config_save_all() -{ - int rc; + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - if ((rc = smb_config_save(SMBD_PG_NAME)) != 0) + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); return (rc); + } - return (smb_config_save(SMBD_PROTECTED_PG_NAME)); + rc = smb_smf_set_integer_property(handle, cfg->sc_name, value); + + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* - * smb_config_save + * smb_config_setbool * - * Scan the config table and call smb_config_setenv/smb_config_unsetenv - * for params in the specified property group that has been modified. - * When the scan is finished, smb_config_saveenv() will be called to - * make the changes persistent. + * Sets a boolean configuration iterm */ -static int -smb_config_save(char *pgname) +int +smb_config_setbool(smb_cfg_id_t id, boolean_t value) { - smb_cfg_id_t id; + smb_scfhandle_t *handle; smb_cfg_param_t *cfg; - smb_scfhandle_t *handle = NULL; - int dorefresh = 0; + int rc = SMBD_SMF_OK; + + cfg = smb_config_getent(id); + assert(cfg->sc_type == SCF_TYPE_BOOLEAN); handle = smb_smf_scf_init(SMBD_FMRI_PREFIX); - if (handle == NULL) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } + if (handle == NULL) + return (SMBD_SMF_SYSTEM_ERR); - (void) smb_smf_create_service_pgroup(handle, pgname); - if (smb_smf_start_transaction(handle) != SMBD_SMF_OK) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } + rc = smb_smf_create_service_pgroup(handle, SMBD_PG_NAME); + if (rc == SMBD_SMF_OK) + rc = smb_smf_start_transaction(handle); - for (id = 0; id < SMB_CI_MAX; id++) { - cfg = &smb_cfg_table[id]; - if (strcmp(cfg->sc_pg, pgname)) - continue; - - if (cfg->sc_flags & SMB_CF_MODIFIED) { - if (cfg->sc_value) { - if (strcmp(pgname, SMBD_PG_NAME) == 0) - smb_config_setenv_trans(handle, - cfg->sc_type, cfg->sc_name, - cfg->sc_value); - else - smb_config_setenv_trans_protected( - handle, cfg->sc_name, - cfg->sc_value); - } else { - (void) smb_config_unsetenv_trans(handle, - cfg->sc_name); - } - cfg->sc_flags &= ~SMB_CF_MODIFIED; - dorefresh = 1; - } + if (rc != SMBD_SMF_OK) { + smb_smf_scf_fini(handle); + return (rc); } - if (smb_config_saveenv(handle) != 0) { - syslog(LOG_ERR, "smbd: cannot save configuration"); - return (1); - } - if (dorefresh) - (void) smf_refresh_instance(SMBD_DEFAULT_INSTANCE_FMRI); - return (0); + rc = smb_smf_set_boolean_property(handle, cfg->sc_name, value); + + (void) smb_smf_end_transaction(handle); + smb_smf_scf_fini(handle); + return (rc); } /* - * smb_config_update + * smb_config_set * - * Updates the specified config param with the given value. - * This function is called both on (re)load and set. + * This function sets the value of the specified config + * iterm regardless of its type in string format. This should + * be used when the config item type is not known by the caller. */ -static int -smb_config_update(smb_cfg_param_t *cfg, char *value) +int +smb_config_set(smb_cfg_id_t id, char *value) { - char *curval; - int rc = 0; - int len; - - if (value) { - len = strlen(value); - if (cfg->sc_value) { - curval = (char *)realloc(cfg->sc_value, - (len + 1)); - } else { - curval = (char *)malloc(len + 1); - } + smb_cfg_param_t *cfg; + int64_t cint; - if (curval) { - cfg->sc_value = curval; - (void) strcpy(cfg->sc_value, value); - cfg->sc_flags |= SMB_CF_DEFINED; - } else { - rc = 1; - } - } else if (cfg->sc_value) { - free(cfg->sc_value); - cfg->sc_value = NULL; - cfg->sc_flags &= ~SMB_CF_DEFINED; + cfg = smb_config_getent(id); + switch (cfg->sc_type) { + case SCF_TYPE_ASTRING: + return (smb_config_setstr(id, value)); + + case SCF_TYPE_INTEGER: + cint = atoi(value); + return (smb_config_setnum(id, cint)); + + case SCF_TYPE_BOOLEAN: + return (smb_config_setbool(id, strcasecmp(value, "true") == 0)); } - return (rc); + return (SMBD_SMF_INVALID_ARG); } - uint8_t smb_config_get_fg_flag() { @@ -1072,9 +737,9 @@ smb_config_secmode_tostr(int secmode) int smb_config_get_secmode() { - char *p; + char p[16]; - p = smb_config_getstr(SMB_CI_SECURITY); + (void) smb_config_getstr(SMB_CI_SECURITY, p, sizeof (p)); return (smb_config_secmode_fromstr(p)); } @@ -1084,5 +749,18 @@ smb_config_set_secmode(int secmode) char *p; p = smb_config_secmode_tostr(secmode); - return (smb_config_set(SMB_CI_SECURITY, p)); + return (smb_config_setstr(SMB_CI_SECURITY, p)); +} + +static smb_cfg_param_t * +smb_config_getent(smb_cfg_id_t id) +{ + int i; + + for (i = 0; i < SMB_CI_MAX; i++) + if (smb_cfg_table[i].sc_id == id) + return (&smb_cfg_table[id]); + + assert(0); + return (NULL); } diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c index 22ea5e61fb..f57dadc806 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_domain.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_domain.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,10 +77,11 @@ int nt_domain_init(char *resource_domain, uint32_t secmode) { nt_domain_t *domain; - nt_sid_t *sid; - char *sidstr; + nt_sid_t *sid = NULL; + char sidstr[128]; char *lsidstr; char hostname[MAXHOSTNAMELEN]; + int rc; if (rwlock_init(&nt_domain_lock, USYNC_THREAD, NULL)) return (SMB_DOMAIN_NODOMAIN_SID); @@ -112,17 +113,18 @@ nt_domain_init(char *resource_domain, uint32_t secmode) (void) nt_domain_add(domain); free(sid); - smb_config_rdlock(); - sidstr = smb_config_get(SMB_CI_DOMAIN_SID); - if (sidstr) { + sid = NULL; + rc = smb_config_getstr(SMB_CI_DOMAIN_SID, sidstr, + sizeof (sidstr)); + if (rc == SMBD_SMF_OK) sid = nt_sid_strtosid(sidstr); - smb_config_unlock(); + if (nt_sid_is_valid(sid)) { domain = nt_domain_new(NT_DOMAIN_PRIMARY, resource_domain, sid); (void) nt_domain_add(domain); free(sid); } else { - smb_config_unlock(); + free(sid); (void) rwlock_destroy(&nt_domain_lock); return (SMB_DOMAIN_NODOMAIN_SID); } @@ -198,9 +200,7 @@ nt_domain_add(nt_domain_t *new_domain) if (new_domain->type == NT_DOMAIN_PRIMARY) { sidstr = nt_sid_format(new_domain->sid); - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_DOMAIN_SID, sidstr); - smb_config_unlock(); + (void) smb_config_setstr(SMB_CI_DOMAIN_SID, sidstr); free(sidstr); } (void) rw_unlock(&nt_domain_lock); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c index 06eeac365c..7884b972a5 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_door_client.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,7 +36,6 @@ #include <strings.h> #include <stdlib.h> #include <errno.h> -#include <unistd.h> #include <smbsrv/smbinfo.h> #include <smbsrv/wintypes.h> @@ -54,7 +53,6 @@ static char *smbd_desc[] = { "SmbdGetParam", "SmbdSetParam", "SmbdNetbiosReconfig", - "SmbdAdsDomainChanged", 0 }; @@ -411,95 +409,3 @@ smbd_get_security_mode(int *mode) *mode = smb_config_secmode_fromstr(buf); return (rc); } - -/* - * smb_ads_domain_change_notify - * - * When ADS domain has changed, this function is called to clear the - * ADS_HOST_INFO cache and remove the old keys from the Kerberos keytab. - */ -int -smb_ads_domain_change_notify(char *dom) -{ - door_arg_t arg; - char *buf; - uint32_t used; - smb_dr_ctx_t *dec_ctx; - smb_dr_ctx_t *enc_ctx; - int status; - int rc; - int opcode = SMBD_DOOR_ADS_DOMAIN_CHANGED; - - if (smbd_door_open(opcode) == -1) { - syslog(LOG_ERR, "%s: cannot open the door", smbd_desc[opcode]); - return (1); - } - - buf = MEM_MALLOC("smb_door_client", SMBD_DOOR_SIZE); - if (!buf) { - syslog(LOG_ERR, "%s: resource shortage", smbd_desc[opcode]); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - enc_ctx = smb_dr_encode_start(buf, SMBD_DOOR_SIZE); - if (enc_ctx == 0) { - syslog(LOG_ERR, "%s: encode start failed", smbd_desc[opcode]); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - smb_dr_put_uint32(enc_ctx, opcode); - smb_dr_put_string(enc_ctx, dom); - - if ((status = smb_dr_encode_finish(enc_ctx, &used)) != 0) { - syslog(LOG_ERR, "%s: Encode error %s", - smbd_desc[opcode], strerror(status)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - arg.data_ptr = buf; - arg.data_size = used; - arg.desc_ptr = NULL; - arg.desc_num = 0; - arg.rbuf = buf; - arg.rsize = SMBD_DOOR_SIZE; - - if (door_call(smb_door_fildes, &arg) < 0) { - syslog(LOG_ERR, "%s: Door call failed %s", smbd_desc[opcode], - strerror(errno)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - - dec_ctx = smb_dr_decode_start(arg.data_ptr, arg.data_size); - if (smbd_door_check_srv_status(opcode, dec_ctx) != 0) { - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - rc = smb_dr_get_uint32(dec_ctx); - - if ((status = smb_dr_decode_finish(dec_ctx)) != 0) { - syslog(LOG_ERR, "%s: Decode error %s", - smbd_desc[opcode], strerror(status)); - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - return (1); - } - MEM_FREE("smb_door_client", buf); - (void) close(smb_door_fildes); - smb_door_fildes = -1; - - return (rc); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c b/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c deleted file mode 100644 index 0b29764926..0000000000 --- a/usr/src/lib/smbsrv/libsmb/common/smb_group_door_encdec.c +++ /dev/null @@ -1,337 +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. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <strings.h> -#include <smbsrv/libsmb.h> -#include <smbsrv/smb_xdr.h> -#include <smbsrv/smb_door_svc.h> - -/* - * smb_grplist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grplist_mkselfrel(ntgrp_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, "smb_grplist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntgrp_list_t, obj); - buf = (uint8_t *)malloc(*len); - - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - - if (!xdr_ntgrp_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grplist_mkselfrel: XDR encode error"); - free(buf); - *len = 0; - buf = NULL; - } - - xdr_destroy(&xdrs); - return (buf); -} - -/* - * smb_grplist_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntgrp_list_t * -smb_grplist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntgrp_list_t *obj; - XDR xdrs; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - - if ((obj = (ntgrp_list_t *) - malloc(sizeof (ntgrp_list_t))) == 0) { - syslog(LOG_ERR, "smb_grplist_mkabsolute: resource shortage"); - xdr_destroy(&xdrs); - return (NULL); - } - bzero(obj, sizeof (ntgrp_list_t)); - if (!xdr_ntgrp_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grplist_mkabsolute: XDR decode error"); - smb_group_free_list(obj, 1); - obj = NULL; - } - - xdr_destroy(&xdrs); - return (obj); -} - -/* - * smb_grpmemberlist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grpmemberlist_mkselfrel(ntgrp_member_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntgrp_member_list_t, obj); - buf = (uint8_t *)malloc(*len); - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - if (!xdr_ntgrp_member_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkselfrel: XDR encode error"); - free(buf); - *len = 0; - buf = NULL; - } - - xdr_destroy(&xdrs); - return (buf); -} - -/* - * ntgrp_list_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntgrp_member_list_t * -smb_grpmemberlist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntgrp_member_list_t *obj = NULL; - XDR xdrs; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - - if ((obj = (ntgrp_member_list_t *) - malloc(sizeof (ntgrp_member_list_t))) == 0) { - xdr_destroy(&xdrs); - syslog(LOG_ERR, - "smb_grpmemberlist_mkabsolute: resource shortage"); - return (NULL); - } - bzero(obj, sizeof (ntgrp_member_list_t)); - bzero(obj->members, SMB_GROUP_PER_LIST * sizeof (members_list)); - if (!xdr_ntgrp_member_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpmemberlist_mkabsolute: XDR decode error"); - smb_group_free_memberlist(obj, 1); - obj = NULL; - } - - xdr_destroy(&xdrs); - return (obj); -} - -/* - * smb_privlist_mkselfrel - * - * encode: structure -> flat buffer (buffer size) - * Pre-condition: obj is non-null. - */ -static uint8_t * -smb_grpprivlist_mkselfrel(ntpriv_list_t *obj, uint32_t *len) -{ - uint8_t *buf; - XDR xdrs; - - if (!obj) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: invalid parameter"); - return (NULL); - } - *len = xdr_sizeof(xdr_ntpriv_list_t, obj); - buf = (uint8_t *)malloc(*len); - if (!buf) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: resource shortage"); - return (NULL); - } - xdrmem_create(&xdrs, (const caddr_t)buf, *len, XDR_ENCODE); - if (!xdr_ntpriv_list_t(&xdrs, obj)) { - syslog(LOG_ERR, - "smb_grpprivlist_mkselfrel: XDR encode error"); - *len = 0; - free(buf); - buf = NULL; - } - xdr_destroy(&xdrs); - return (buf); -} - -/* - * smb_privlist_mkabsolute - * - * decode: flat buffer -> structure - */ -static ntpriv_list_t * -smb_grpprivlist_mkabsolute(uint8_t *buf, uint32_t len) -{ - ntpriv_list_t *obj = NULL; - XDR xdrs; - uint32_t status; - int length = 0, num_privs = 0; - - xdrmem_create(&xdrs, (const caddr_t)buf, len, XDR_DECODE); - status = smb_group_priv_num(&num_privs); - if (status != 0) { - syslog(LOG_ERR, - "smb_grpprivlist_mkabsolute: Cannot get privlist."); - xdr_destroy(&xdrs); - return (NULL); - } - - if (num_privs > 0) { - length = sizeof (int) + (num_privs * sizeof (privs_t)); - if ((obj = (ntpriv_list_t *)malloc(length)) == 0) { - syslog(LOG_ERR, - "smb_grpprivlist_mkabsolute: resource shortage"); - xdr_destroy(&xdrs); - return (NULL); - } - } - bzero(obj, sizeof (ntpriv_list_t)); - bzero(obj->privs, num_privs * sizeof (privs_t)); - if (!xdr_ntpriv_list_t(&xdrs, obj)) { - syslog(LOG_ERR, "smb_grpprivlist_mkabsolute: XDR decode error"); - smb_group_free_privlist(obj, 1); - obj = NULL; - } - xdr_destroy(&xdrs); - return (obj); -} - -char * -smb_dr_encode_grp_list(uint32_t opcode, ntgrp_list_t *list, - size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grplist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntgrp_list_t * -smb_dr_decode_grp_list(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntgrp_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, "smb_dr_decode_grplist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grplist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} - -char * -smb_dr_encode_grp_memberlist(uint32_t opcode, - ntgrp_member_list_t *list, size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grpmemberlist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntgrp_member_list_t * -smb_dr_decode_grp_memberlist(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntgrp_member_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, - "smb_dr_decode_grpmemberlist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grpmemberlist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} - -char * -smb_dr_encode_grp_privlist(uint32_t opcode, - ntpriv_list_t *list, size_t *len) -{ - char *buf; - smb_dr_bytes_t arg; - - arg.bytes_val = smb_grpprivlist_mkselfrel(list, &arg.bytes_len); - - buf = smb_dr_encode_common(opcode, &arg, xdr_smb_dr_bytes_t, len); - free(arg.bytes_val); - return (buf); -} - -ntpriv_list_t * -smb_dr_decode_grp_privlist(char *buf, size_t len) -{ - smb_dr_bytes_t arg; - ntpriv_list_t *list; - - bzero(&arg, sizeof (smb_dr_bytes_t)); - if (smb_dr_decode_common(buf, len, xdr_smb_dr_bytes_t, &arg) - != 0) { - syslog(LOG_ERR, "smb_dr_decode_grp_privlist: XDR decode error"); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (NULL); - } - list = smb_grpprivlist_mkabsolute(arg.bytes_val, arg.bytes_len); - xdr_free(xdr_smb_dr_bytes_t, (char *)&arg); - return (list); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c b/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c deleted file mode 100644 index 723a6471f9..0000000000 --- a/usr/src/lib/smbsrv/libsmb/common/smb_group_xdr.c +++ /dev/null @@ -1,158 +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. - */ - -#include <rpc/rpc.h> -#include <smbsrv/libsmb.h> - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file was originally generated using rpcgen. - */ - -bool_t -xdr_ntgrp_dr_arg_t(xdrs, objp) - XDR *xdrs; - ntgrp_dr_arg_t *objp; -{ - if (!xdr_string(xdrs, &objp->gname, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->desc, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->member, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->newgname, ~0)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->privid)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->priv_attr)) - return (FALSE); - if (!xdr_int(xdrs, &objp->offset)) - return (FALSE); - if (!xdr_string(xdrs, &objp->scope, ~0)) - return (FALSE); - if (!xdr_int(xdrs, &objp->type)) - return (FALSE); - if (!xdr_int(xdrs, &objp->count)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->ntstatus)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_t(xdrs, objp) - XDR *xdrs; - ntgrp_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->rid)) - return (FALSE); - if (!xdr_string(xdrs, &objp->name, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->desc, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->type, ~0)) - return (FALSE); - if (!xdr_string(xdrs, &objp->sid, ~0)) - return (FALSE); - if (!xdr_uint32_t(xdrs, &objp->attr)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_list_t(xdrs, objp) - XDR *xdrs; - ntgrp_list_t *objp; -{ - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->groups, SMB_GROUP_PER_LIST, - sizeof (ntgrp_t), (xdrproc_t)xdr_ntgrp_t)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_members_list(xdrs, objp) - XDR *xdrs; - members_list *objp; -{ - if (!xdr_string(xdrs, objp, ~0)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntgrp_member_list_t(xdrs, objp) - XDR *xdrs; - ntgrp_member_list_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->rid)) - return (FALSE); - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->members, SMB_GROUP_PER_LIST, - sizeof (members_list), (xdrproc_t)xdr_members_list)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntpriv_t(xdrs, objp) - XDR *xdrs; - ntpriv_t *objp; -{ - if (!xdr_uint32_t(xdrs, &objp->id)) - return (FALSE); - if (!xdr_string(xdrs, &objp->name, ~0)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_privs_t(xdrs, objp) - XDR *xdrs; - privs_t *objp; -{ - if (!xdr_pointer(xdrs, (char **)objp, sizeof (ntpriv_t), - (xdrproc_t)xdr_ntpriv_t)) - return (FALSE); - return (TRUE); -} - -bool_t -xdr_ntpriv_list_t(xdrs, objp) - XDR *xdrs; - ntpriv_list_t *objp; -{ - if (!xdr_int(xdrs, &objp->cnt)) - return (FALSE); - if (!xdr_vector(xdrs, (char *)objp->privs, objp->cnt, - sizeof (privs_t), (xdrproc_t)xdr_privs_t)) - return (FALSE); - return (TRUE); -} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c index f410fe3237..862bcf919d 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -126,6 +126,43 @@ smb_idmap_getsid(uid_t id, int idtype, nt_sid_t **sid) } /* + * smb_idmap_getid + * + * Tries to get a mapping for the given SID + */ +idmap_stat +smb_idmap_getid(nt_sid_t *sid, uid_t *id, int *id_type) +{ + smb_idmap_batch_t sib; + smb_idmap_t *sim; + idmap_stat stat; + + stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_SID2ID); + if (stat != IDMAP_SUCCESS) + return (stat); + + sim = &sib.sib_maps[0]; + sim->sim_id = id; + stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, sid, *id_type); + if (stat != IDMAP_SUCCESS) { + smb_idmap_batch_destroy(&sib); + return (stat); + } + + stat = smb_idmap_batch_getmappings(&sib); + + if (stat != IDMAP_SUCCESS) { + smb_idmap_batch_destroy(&sib); + return (stat); + } + + *id_type = sim->sim_idtype; + smb_idmap_batch_destroy(&sib); + + return (IDMAP_SUCCESS); +} + +/* * smb_idmap_batch_create * * Creates and initializes the context for batch ID mapping. @@ -163,7 +200,6 @@ void smb_idmap_batch_destroy(smb_idmap_batch_t *sib) { nt_sid_t *sid; - char *domsid; int i; if (!sib) @@ -177,8 +213,7 @@ smb_idmap_batch_destroy(smb_idmap_batch_t *sib) if (!sib->sib_maps) return; - switch (sib->sib_flags) { - case SMB_IDMAP_SID2ID: + if (sib->sib_flags & SMB_IDMAP_ID2SID) { /* * SIDs are allocated only when mapping * UID/GID to SIDs @@ -188,20 +223,6 @@ smb_idmap_batch_destroy(smb_idmap_batch_t *sib) if (sid) free(sid); } - break; - case SMB_IDMAP_ID2SID: - /* - * SID prefixes are allocated only when mapping - * SIDs to UID/GID - */ - for (i = 0; i < sib->sib_nmap; i++) { - domsid = sib->sib_maps[i].sim_domsid; - if (domsid) - free(domsid); - } - break; - default: - break; } if (sib->sib_size && sib->sib_maps) { @@ -262,9 +283,11 @@ smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, break; default: + free(sim->sim_domsid); return (IDMAP_ERR_ARG); } + free(sim->sim_domsid); return (stat); } @@ -371,6 +394,7 @@ smb_idmap_batch_binsid(smb_idmap_batch_t *sib) return (-1); sid = nt_sid_strtosid(sim->sim_domsid); + free(sim->sim_domsid); if (sid == NULL) return (-1); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c index d39eaf9208..918cc02acb 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +37,9 @@ #include <errno.h> #include <net/if.h> #include <netdb.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> #include <sys/sockio.h> #include <smbsrv/smbinfo.h> #include <smbsrv/netbios.h> @@ -48,85 +51,6 @@ static cond_t smbpdc_cv; extern int getdomainname(char *, int); -uint32_t -smb_get_security_mode() -{ - uint32_t mode; - - smb_config_rdlock(); - mode = smb_config_get_secmode(); - smb_config_unlock(); - - return (mode); -} - -/* - * smb_purge_domain_info - * - * Clean out the environment in preparation for joining a domain. - * This ensures that we don't have any old information lying around. - */ -void -smb_purge_domain_info(void) -{ - smb_config_wrlock(); - (void) smb_config_set(SMB_CI_DOMAIN_NAME, 0); - (void) smb_config_set(SMB_CI_DOMAIN_SID, 0); - (void) smb_config_set(SMB_CI_DOMAIN_MEMB, 0); - smb_config_unlock(); -} - -int -smb_is_domain_member(void) -{ - int is_memb; - - smb_config_rdlock(); - is_memb = smb_config_getyorn(SMB_CI_DOMAIN_MEMB); - smb_config_unlock(); - - return (is_memb); -} - -uint8_t -smb_get_fg_flag(void) -{ - uint8_t run_fg; - - smb_config_rdlock(); - run_fg = smb_config_get_fg_flag(); - smb_config_unlock(); - - return (run_fg); -} - -void -smb_set_domain_member(int set) -{ - char *member; - - smb_config_wrlock(); - member = (set) ? "true" : "false"; - (void) smb_config_set(SMB_CI_DOMAIN_MEMB, member); - smb_config_unlock(); -} - -/* - * smb_set_machine_pwd - * - * Returns 0 upon success. Otherwise, returns 1. - */ -int -smb_set_machine_pwd(char *pwd) -{ - int rc; - - smb_config_wrlock(); - rc = smb_config_set(SMB_CI_MACHINE_PASSWD, pwd); - smb_config_unlock(); - return (rc); -} - /* * smb_getdomaininfo * @@ -206,47 +130,41 @@ smb_setdomaininfo(char *domain, char *server, uint32_t ipaddr) void smb_load_kconfig(smb_kmod_cfg_t *kcfg) { - smb_config_rdlock(); + int64_t citem; + bzero(kcfg, sizeof (smb_kmod_cfg_t)); - kcfg->skc_maxbufsize = smb_config_getnum(SMB_CI_MAX_BUFSIZE); - kcfg->skc_maxworkers = smb_config_getnum(SMB_CI_MAX_WORKERS); - kcfg->skc_keepalive = smb_config_getnum(SMB_CI_KEEPALIVE); + (void) smb_config_getnum(SMB_CI_MAX_BUFSIZE, &citem); + kcfg->skc_maxbufsize = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_MAX_WORKERS, &citem); + kcfg->skc_maxworkers = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_KEEPALIVE, &citem); + kcfg->skc_keepalive = (uint32_t)citem; if ((kcfg->skc_keepalive != 0) && (kcfg->skc_keepalive < SMB_PI_KEEP_ALIVE_MIN)) kcfg->skc_keepalive = SMB_PI_KEEP_ALIVE_MIN; - kcfg->skc_restrict_anon = smb_config_getyorn(SMB_CI_RESTRICT_ANON); - - kcfg->skc_signing_enable = smb_config_getyorn(SMB_CI_SIGNING_ENABLE); - kcfg->skc_signing_required = smb_config_getyorn(SMB_CI_SIGNING_REQD); - kcfg->skc_signing_check = smb_config_getyorn(SMB_CI_SIGNING_CHECK); - kcfg->skc_oplock_enable = smb_config_getyorn(SMB_CI_OPLOCK_ENABLE); - kcfg->skc_oplock_timeout = smb_config_getnum(SMB_CI_OPLOCK_TIMEOUT); - - kcfg->skc_flush_required = smb_config_getyorn(SMB_CI_FLUSH_REQUIRED); - kcfg->skc_sync_enable = smb_config_getyorn(SMB_CI_SYNC_ENABLE); + (void) smb_config_getnum(SMB_CI_OPLOCK_TIMEOUT, &citem); + kcfg->skc_oplock_timeout = (uint32_t)citem; + (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &citem); + kcfg->skc_maxconnections = (uint32_t)citem; + 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_signing_check = smb_config_getbool(SMB_CI_SIGNING_CHECK); + kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE); + kcfg->skc_flush_required = smb_config_getbool(SMB_CI_FLUSH_REQUIRED); + kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE); kcfg->skc_dirsymlink_enable = - !smb_config_getyorn(SMB_CI_DIRSYMLINK_DISABLE); - kcfg->skc_announce_quota = smb_config_getyorn(SMB_CI_ANNONCE_QUOTA); - kcfg->skc_announce_quota = smb_config_getyorn(SMB_CI_ANNONCE_QUOTA); - + !smb_config_getbool(SMB_CI_DIRSYMLINK_DISABLE); + kcfg->skc_announce_quota = smb_config_getbool(SMB_CI_ANNONCE_QUOTA); kcfg->skc_secmode = smb_config_get_secmode(); - kcfg->skc_lmlevel = smb_config_getnum(SMB_CI_LM_LEVEL); - kcfg->skc_maxconnections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); - - (void) strlcpy(kcfg->skc_resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), + (void) smb_getdomainname(kcfg->skc_resource_domain, sizeof (kcfg->skc_resource_domain)); - - (void) smb_gethostname(kcfg->skc_hostname, - sizeof (kcfg->skc_hostname), 1); - - (void) strlcpy(kcfg->skc_system_comment, - smb_config_getstr(SMB_CI_SYS_CMNT), + (void) smb_gethostname(kcfg->skc_hostname, sizeof (kcfg->skc_hostname), + 1); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, kcfg->skc_system_comment, sizeof (kcfg->skc_system_comment)); - - smb_config_unlock(); } /* @@ -304,74 +222,200 @@ smb_gethostname(char *buf, size_t buflen, int upcase) } /* - * The ADS domain is often the same as the DNS domain but they can be - * different - one might be a sub-domain of the other. - * - * If an ADS domain name has been configured, return it. Otherwise, - * return the DNS domain name. - * - * If getdomainname fails, the returned buffer will contain an empty - * string. + * Obtain the fully-qualified name for this machine. If the + * hostname is fully-qualified, accept it. Otherwise, try to + * find an appropriate domain name to append to the hostname. */ int -smb_getdomainname(char *buf, size_t buflen) +smb_getfqhostname(char *buf, size_t buflen) { - char *domain; + char hostname[MAXHOSTNAMELEN]; + char domain[MAXHOSTNAMELEN]; - if (buf == NULL || buflen == 0) + hostname[0] = '\0'; + domain[0] = '\0'; + + if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) return (-1); - smb_config_rdlock(); + if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) + return (-1); + + if (hostname[0] == '\0') + return (-1); - domain = smb_config_getstr(SMB_CI_ADS_DOMAIN); - if ((domain != NULL) && (*domain != '\0')) { - (void) strlcpy(buf, domain, buflen); - smb_config_unlock(); + if (domain[0] == '\0') { + (void) strlcpy(buf, hostname, buflen); return (0); } - smb_config_unlock(); + (void) snprintf(buf, buflen, "%s.%s", hostname, domain); + return (0); +} - if (getdomainname(buf, buflen) != 0) { - *buf = '\0'; +/* + * smb_resolve_netbiosname + * + * Convert the fully-qualified domain name (i.e. fqdn) to a NETBIOS name. + * Upon success, the NETBIOS name will be returned via buf parameter. + * Returns 0 upon success. Otherwise, returns -1. + */ +int +smb_resolve_netbiosname(char *fqdn, char *buf, size_t buflen) +{ + char *p; + + if (!buf) return (-1); - } + + *buf = '\0'; + if (!fqdn) + return (-1); + + (void) strlcpy(buf, fqdn, buflen); + if ((p = strchr(buf, '.')) != NULL) + *p = 0; + + if (strlen(buf) >= NETBIOS_NAME_SZ) + buf[NETBIOS_NAME_SZ - 1] = '\0'; return (0); } /* - * Obtain the fully-qualified name for this machine. If the - * hostname is fully-qualified, accept it. Otherwise, try to - * find an appropriate domain name to append to the hostname. + * smb_getdomainname + * + * Returns NETBIOS name of the domain if the system is in domain + * mode. Or returns workgroup name if the system is in workgroup + * mode. */ int -smb_getfqhostname(char *buf, size_t buflen) +smb_getdomainname(char *buf, size_t buflen) { - char hostname[MAXHOSTNAMELEN]; char domain[MAXHOSTNAMELEN]; + int rc; - hostname[0] = '\0'; - domain[0] = '\0'; + if (buf == NULL || buflen == 0) + return (-1); - if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) + *buf = '\0'; + rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, domain, + sizeof (domain)); + + if ((rc != SMBD_SMF_OK) || (*domain == '\0')) return (-1); - if (smb_getdomainname(domain, MAXHOSTNAMELEN) != 0) + (void) smb_resolve_netbiosname(domain, buf, buflen); + return (0); +} + +/* + * smb_resolve_fqdn + * + * Converts the NETBIOS name of the domain (i.e. nbt_domain) to a fully + * qualified domain name. The domain from either the domain field or + * search list field of the /etc/resolv.conf will be returned via the + * buf parameter if the first label of the domain matches the given + * NETBIOS name. + * + * Returns -1 upon error. If a match is found, returns 1. Otherwise, + * returns 0. + */ +int +smb_resolve_fqdn(char *nbt_domain, char *buf, size_t buflen) +{ + struct __res_state res_state; + int i, found = 0; + char *p; + int dlen; + + if (!buf) return (-1); - if (hostname[0] == '\0') + *buf = '\0'; + if (!nbt_domain) return (-1); - if (domain[0] == '\0') { - (void) strlcpy(buf, hostname, buflen); - return (0); + bzero(&res_state, sizeof (struct __res_state)); + if (res_ninit(&res_state)) + return (-1); + + if (*nbt_domain == '\0') { + if (*res_state.defdname == '\0') { + res_ndestroy(&res_state); + return (0); + } + + (void) strlcpy(buf, res_state.defdname, buflen); + res_ndestroy(&res_state); + return (1); } - (void) snprintf(buf, buflen, "%s.%s", hostname, domain); - return (0); + dlen = strlen(nbt_domain); + if (!strncasecmp(nbt_domain, res_state.defdname, dlen)) { + (void) strlcpy(buf, res_state.defdname, buflen); + res_ndestroy(&res_state); + return (1); + } + + for (i = 0; (p = res_state.dnsrch[i]) != NULL; i++) { + if (!strncasecmp(nbt_domain, p, dlen)) { + (void) strlcpy(buf, p, buflen); + found = 1; + break; + } + + } + + res_ndestroy(&res_state); + return (found); +} + +/* + * smb_getfqdomainname + * + * If the domain_name property value is FQDN, it will be returned. + * In domain mode, the domain from either the domain field or + * search list field of the /etc/resolv.conf will be returned via the + * buf parameter if the first label of the domain matches the + * domain_name property. In workgroup mode, it returns the local + * domain. + * + * Returns 0 upon success. Otherwise, returns -1. + */ +int +smb_getfqdomainname(char *buf, size_t buflen) +{ + char domain[MAXHOSTNAMELEN]; + int rc = 0; + + if (buf == NULL || buflen == 0) + return (-1); + + *buf = '\0'; + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) { + rc = smb_config_getstr(SMB_CI_DOMAIN_NAME, domain, + sizeof (domain)); + + if ((rc != SMBD_SMF_OK) || (*domain == '\0')) + return (-1); + + if (strchr(domain, '.') == NULL) { + if (smb_resolve_fqdn(domain, buf, buflen) != 1) + rc = -1; + } else { + (void) strlcpy(buf, domain, buflen); + } + } else { + if (smb_resolve_fqdn("", buf, buflen) != 1) + rc = -1; + } + + return (rc); } + + /* * Temporary fbt for dtrace until user space sdt enabled. */ diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c new file mode 100644 index 0000000000..934b804dcd --- /dev/null +++ b/usr/src/lib/smbsrv/libsmb/common/smb_lgrp.c @@ -0,0 +1,2319 @@ +/* + * 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" + +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> +#include <syslog.h> +#include <thread.h> +#include <synch.h> +#include <grp.h> +#include <assert.h> +#include <libintl.h> +#include <smbsrv/libsmb.h> + +#define SMB_LGRP_LOCAL_IDX 0 +#define SMB_LGRP_BUILTIN_IDX 1 + +#define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db" +#define SMB_LGRP_DB_TIMEOUT 3000 /* in millisecond */ +#define SMB_LGRP_DB_VERMAJOR 1 +#define SMB_LGRP_DB_VERMINOR 0 +#define SMB_LGRP_DB_MAGIC 0x4C475250 /* LGRP */ + +#define SMB_LGRP_DB_ORD 1 /* open read-only */ +#define SMB_LGRP_DB_ORW 2 /* open read/write */ + +#define SMB_LGRP_DB_ADDMEMBER 1 +#define SMB_LGRP_DB_DELMEMBER 2 + +/* + * members column of the groups table is an array of + * member structure smb_lgmid_t defined below. + * + * privs column of the groups table is an array of bytes + * where each byte is the id of an enable privilege + */ +#define SMB_LGRP_DB_SQL \ + "CREATE TABLE db_info (" \ + " ver_major INTEGER," \ + " ver_minor INTEGER," \ + " magic INTEGER" \ + ");" \ + "" \ + "CREATE TABLE domains (" \ + " dom_idx INTEGER PRIMARY KEY," \ + " dom_sid TEXT UNIQUE," \ + " dom_cnt INTEGER" \ + ");" \ + "" \ + "CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \ + "" \ + "CREATE TABLE groups (" \ + " name TEXT PRIMARY KEY," \ + " sid_idx INTEGER," \ + " sid_rid INTEGER," \ + " sid_type INTEGER," \ + " sid_attrs INTEGER," \ + " comment TEXT," \ + " n_privs INTEGER," \ + " privs BLOB," \ + " n_members INTEGER," \ + " members BLOB" \ + ");" \ + "" \ + "CREATE INDEX grprid_idx ON groups (sid_rid);" + +/* + * Number of groups table columns + */ +#define SMB_LGRP_GTBL_NCOL 10 + +#define SMB_LGRP_GTBL_NAME 0 +#define SMB_LGRP_GTBL_SIDIDX 1 +#define SMB_LGRP_GTBL_SIDRID 2 +#define SMB_LGRP_GTBL_SIDTYP 3 +#define SMB_LGRP_GTBL_SIDATR 4 +#define SMB_LGRP_GTBL_CMNT 5 +#define SMB_LGRP_GTBL_NPRIVS 6 +#define SMB_LGRP_GTBL_PRIVS 7 +#define SMB_LGRP_GTBL_NMEMBS 8 +#define SMB_LGRP_GTBL_MEMBS 9 + +#define SMB_LGRP_INFO_NONE 0x00 +#define SMB_LGRP_INFO_NAME 0x01 +#define SMB_LGRP_INFO_CMNT 0x02 +#define SMB_LGRP_INFO_SID 0x04 +#define SMB_LGRP_INFO_PRIV 0x08 +#define SMB_LGRP_INFO_MEMB 0x10 +#define SMB_LGRP_INFO_ALL 0x1F + +#define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL") + +/* Member ID */ +typedef struct smb_lgmid { + uint32_t m_idx; + uint32_t m_rid; + uint16_t m_type; +} smb_lgmid_t; + +#define SMB_LGRP_MID_HEXSZ 32 + +/* Member list */ +typedef struct smb_lgmlist { + uint32_t m_cnt; + char *m_ids; +} smb_lgmlist_t; + +/* Privilege ID */ +typedef uint8_t smb_lgpid_t; + +/* Privilege list */ +typedef struct smb_lgplist { + uint32_t p_cnt; + smb_lgpid_t *p_ids; +} smb_lgplist_t; + +static mutex_t smb_lgrp_lsid_mtx; +static nt_sid_t *smb_lgrp_lsid; + +static int smb_lgrp_db_init(void); +static sqlite *smb_lgrp_db_open(int); +static void smb_lgrp_db_close(sqlite *); +static int smb_lgrp_db_setinfo(sqlite *); + +static boolean_t smb_lgrp_gtbl_exists(sqlite *, char *); +static int smb_lgrp_gtbl_lookup(sqlite *, int, smb_group_t *, int, ...); +static int smb_lgrp_gtbl_insert(sqlite *, smb_group_t *); +static int smb_lgrp_gtbl_update(sqlite *, char *, smb_group_t *, int); +static int smb_lgrp_gtbl_delete(sqlite *, char *); +static int smb_lgrp_gtbl_update_mlist(sqlite *, char *, smb_gsid_t *, int); +static int smb_lgrp_gtbl_update_plist(sqlite *, char *, uint8_t, boolean_t); +static int smb_lgrp_gtbl_count(sqlite *, int, int *); + +static int smb_lgrp_dtbl_insert(sqlite *, char *, uint32_t *); +static int smb_lgrp_dtbl_getidx(sqlite *, nt_sid_t *, uint16_t, + uint32_t *, uint32_t *); +static int smb_lgrp_dtbl_getsid(sqlite *, uint32_t, nt_sid_t **); + +static int smb_lgrp_mlist_add(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); +static int smb_lgrp_mlist_del(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); + +static int smb_lgrp_plist_add(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); +static int smb_lgrp_plist_del(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); + +static void smb_lgrp_encode_privset(smb_group_t *, smb_lgplist_t *); + +static int smb_lgrp_decode(smb_group_t *, char **, int, sqlite *); +static int smb_lgrp_decode_privset(smb_group_t *, char *, char *); +static int smb_lgrp_decode_members(smb_group_t *, char *, char *, sqlite *); + +static void smb_lgrp_set_default_privs(smb_group_t *); +static boolean_t smb_lgrp_chkname(char *); +static boolean_t smb_lgrp_chkmember(uint16_t); +static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, nt_sid_t **); + +#ifdef _LP64 +/* + * We cannot make 64-bit version of libsqlite because the code + * has some problems. + */ + +/*ARGSUSED*/ +sqlite * +sqlite_open(const char *filename, int mode, char **errmsg) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_close(sqlite *db) +{ +} + +/*ARGSUSED*/ +char * +sqlite_mprintf(const char *fmt, ...) +{ + return (NULL); +} + +/*ARGSUSED*/ +void +sqlite_freemem(void *p) +{ +} + +/*ARGSUSED*/ +int +sqlite_compile(sqlite *db, const char *zSql, const char **pzTail, + sqlite_vm **ppVm, char **pzErrmsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +void +sqlite_free_table(char **res) +{ +} + +/*ARGSUSED*/ +int +sqlite_last_insert_rowid(sqlite *db) +{ + return (-1); +} + +/*ARGSUSED*/ +void +sqlite_busy_timeout(sqlite *db, int ms) +{ +} + +/*ARGSUSED*/ +int +sqlite_get_table(sqlite *db, const char *zSql, char ***pazResult, int *pnRow, + int *pnColumn, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_step(sqlite_vm *pVm, int *pN, const char ***pazValue, + const char ***pazColName) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_exec(sqlite *db, const char *zSql, sqlite_callback xCallback, void *pArg, + char **pzErrMsg) +{ + return (SQLITE_ERROR); +} + +/*ARGSUSED*/ +int +sqlite_finalize(sqlite_vm *pVm, char **pzErrMsg) +{ + return (SQLITE_ERROR); +} +#endif /* _LP64 */ + +/* + * smb_lgrp_add + * + * Create a local group with the given name and comment. + * This new group doesn't have any members and no enabled + * privileges. + * + * No well-known accounts can be added other than Administators, + * Backup Operators and Power Users. These built-in groups + * won't have any members when created but a set of default + * privileges will be enabled for them. + */ +int +smb_lgrp_add(char *gname, char *cmnt) +{ + well_known_account_t *wk_acct; + struct group *pxgrp; + smb_group_t grp; + nt_sid_t *sid = NULL; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) + return (SMB_LGRP_INVALID_ARG); + + bzero(&grp, sizeof (grp)); + grp.sg_name = utf8_strlwr(gname); + grp.sg_cmnt = cmnt; + + wk_acct = nt_builtin_lookup(gname); + if (wk_acct == NULL) { + if ((pxgrp = getgrnam(gname)) == NULL) + return (SMB_LGRP_NOT_FOUND); + + /* + * Make sure a local SID can be obtained + */ + if (smb_idmap_getsid(pxgrp->gr_gid, SMB_IDMAP_GROUP, &sid) + != IDMAP_SUCCESS) + return (SMB_LGRP_NO_SID); + + if (!nt_sid_is_indomain(smb_lgrp_lsid, sid)) { + free(sid); + return (SMB_LGRP_SID_NOTLOCAL); + } + + grp.sg_id.gs_type = SidTypeAlias; + grp.sg_domain = SMB_LGRP_LOCAL; + grp.sg_rid = pxgrp->gr_gid; + } else { + if (wk_acct->flags & LGF_HIDDEN) { + /* cannot add well-known accounts */ + return (SMB_LGRP_WKSID); + } + + grp.sg_id.gs_type = wk_acct->sid_name_use; + if ((sid = nt_sid_strtosid(wk_acct->sid)) == NULL) + return (SMB_LGRP_NO_MEMORY); + (void) nt_sid_get_rid(sid, &grp.sg_rid); + free(sid); + grp.sg_domain = SMB_LGRP_BUILTIN; + + grp.sg_privs = smb_privset_new(); + smb_lgrp_set_default_privs(&grp); + } + + + grp.sg_attr = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | + SE_GROUP_ENABLED; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_insert(db, &grp); + smb_lgrp_db_close(db); + + smb_privset_free(grp.sg_privs); + return (rc); +} + +/* + * smb_lgrp_rename + * + * Renames the given group + */ +int +smb_lgrp_rename(char *gname, char *new_gname) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + (void) trim_whitespace(new_gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (utf8_strcasecmp(gname, new_gname) == 0) + return (SMB_LGRP_SUCCESS); + + /* Cannot rename well-known groups */ + if (nt_builtin_is_wellknown(gname)) + return (SMB_LGRP_WKSID); + + /* Cannot rename to a well-known groups */ + if (nt_builtin_is_wellknown(new_gname)) + return (SMB_LGRP_WKSID); + + grp.sg_name = new_gname; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_NAME); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_delete + * + * Deletes the specified local group. + */ +int +smb_lgrp_delete(char *gname) +{ + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + /* Cannot remove a built-in group */ + if (nt_builtin_is_wellknown(gname)) + return (SMB_LGRP_WKSID); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_delete(db, gname); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_setcmnt + * + * Sets the description for the given group + */ +int +smb_lgrp_setcmnt(char *gname, char *cmnt) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) + return (SMB_LGRP_INVALID_ARG); + + grp.sg_cmnt = cmnt; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_CMNT); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getcmnt + * + * Obtain the description of the specified group + */ +int +smb_lgrp_getcmnt(char *gname, char **cmnt) +{ + smb_group_t grp; + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (cmnt == NULL) + return (SMB_LGRP_INVALID_ARG); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, + SMB_LGRP_INFO_CMNT, gname); + smb_lgrp_db_close(db); + + if (rc == SMB_LGRP_SUCCESS) { + *cmnt = grp.sg_cmnt; + grp.sg_cmnt = NULL; + smb_lgrp_free(&grp); + } + + return (rc); +} + + +/* + * smb_lgrp_setpriv + * + * Enable/disable the specified privilge for the group + */ +int +smb_lgrp_setpriv(char *gname, uint8_t priv_lid, boolean_t enable) +{ + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) + return (SMB_LGRP_NO_SUCH_PRIV); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_plist(db, gname, priv_lid, enable); + smb_lgrp_db_close(db); + + if (enable) { + if (rc == SMB_LGRP_PRIV_HELD) + rc = SMB_LGRP_SUCCESS; + } else { + if (rc == SMB_LGRP_PRIV_NOT_HELD) + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_getpriv + * + * Obtain the status of the specified privilge for the group + */ +int +smb_lgrp_getpriv(char *gname, uint8_t priv_lid, boolean_t *enable) +{ + sqlite *db; + smb_group_t grp; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) + return (SMB_LGRP_NO_SUCH_PRIV); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, + SMB_LGRP_INFO_PRIV, gname); + smb_lgrp_db_close(db); + + if (rc == SMB_LGRP_SUCCESS) { + *enable = (smb_privset_query(grp.sg_privs, priv_lid) == 1); + smb_lgrp_free(&grp); + } + + return (rc); +} + +/* + * smb_lgrp_add_member + * + * Add the given account to the specified group as its member. + */ +int +smb_lgrp_add_member(char *gname, nt_sid_t *msid, uint16_t sid_type) +{ + sqlite *db; + smb_gsid_t mid; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (!nt_sid_is_valid(msid)) + return (SMB_LGRP_INVALID_ARG); + + if (!smb_lgrp_chkmember(sid_type)) + return (SMB_LGRP_INVALID_MEMBER); + + mid.gs_sid = msid; + mid.gs_type = sid_type; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_ADDMEMBER); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_del_member + * + * Delete the specified member from the given group. + */ +int +smb_lgrp_del_member(char *gname, nt_sid_t *msid, uint16_t sid_type) +{ + sqlite *db; + smb_gsid_t mid; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + if (!nt_sid_is_valid(msid)) + return (SMB_LGRP_INVALID_ARG); + + mid.gs_sid = msid; + mid.gs_type = sid_type; + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); + rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_DELMEMBER); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getbyname + * + * Retrieves the information of the group specified by + * the given name. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +int +smb_lgrp_getbyname(char *gname, smb_group_t *grp) +{ + sqlite *db; + int rc; + + (void) trim_whitespace(gname); + if (!smb_lgrp_chkname(gname)) + return (SMB_LGRP_INVALID_NAME); + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, grp, + SMB_LGRP_INFO_ALL, gname); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_getbyrid + * + * Retrieves the information of the group specified by + * the given RID and domain type. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + * + * If grp is NULL no information would be returned. The + * return value of SMB_LGRP_SUCCESS will indicate that a + * group with the given information exists. + */ +int +smb_lgrp_getbyrid(uint32_t rid, smb_gdomain_t domtype, smb_group_t *grp) +{ + smb_group_t tmpgrp; + sqlite *db; + int infolvl = SMB_LGRP_INFO_ALL; + int rc; + + if (grp == NULL) { + grp = &tmpgrp; + infolvl = SMB_LGRP_INFO_NONE; + } + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_SIDRID, grp, infolvl, + rid, domtype); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_numbydomain + * + * Returns the number of groups in the given domain in the + * arg 'count' + */ +int +smb_lgrp_numbydomain(smb_gdomain_t dom_type, int *count) +{ + sqlite *db; + int dom_idx; + int rc; + + switch (dom_type) { + case SMB_LGRP_LOCAL: + dom_idx = SMB_LGRP_LOCAL_IDX; + break; + case SMB_LGRP_BUILTIN: + dom_idx = SMB_LGRP_BUILTIN_IDX; + break; + default: + *count = 0; + return (SMB_LGRP_INVALID_ARG); + } + + db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + rc = smb_lgrp_gtbl_count(db, dom_idx, count); + smb_lgrp_db_close(db); + + return (rc); +} + +/* + * smb_lgrp_numbydomain + * + * Returns the number of groups which have the given SID + * as a member. + */ +int +smb_lgrp_numbymember(nt_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 + * group structure. Note that this function doesn't free + * the group itself. + */ +void +smb_lgrp_free(smb_group_t *grp) +{ + int i; + + if (grp == NULL) + return; + + free(grp->sg_name); + free(grp->sg_cmnt); + free(grp->sg_id.gs_sid); + smb_privset_free(grp->sg_privs); + + for (i = 0; i < grp->sg_nmembers; i++) + free(grp->sg_members[i].gs_sid); + free(grp->sg_members); +} + +/* + * smb_lgrp_iteropen + * + * Initializes the given group iterator by opening + * the group database and creating a virtual machine + * for iteration. + */ +int +smb_lgrp_iteropen(smb_giter_t *iter) +{ + char *sql; + char *errmsg = NULL; + int rc = SMB_LGRP_SUCCESS; + + assert(iter); + + bzero(iter, sizeof (smb_giter_t)); + + sql = sqlite_mprintf("SELECT * FROM groups"); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + iter->sgi_db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); + if (iter->sgi_db == NULL) { + sqlite_freemem(sql); + return (SMB_LGRP_DBOPEN_FAILED); + } + + rc = sqlite_compile(iter->sgi_db, sql, NULL, &iter->sgi_vm, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to create a VM (%s)", + NULL_MSGCHK(errmsg)); + rc = SMB_LGRP_DB_ERROR; + } + + return (rc); +} + +/* + * smb_lgrp_iterclose + * + * Closes the given group iterator. + */ +void +smb_lgrp_iterclose(smb_giter_t *iter) +{ + char *errmsg = NULL; + int rc; + + assert(iter); + + rc = sqlite_finalize(iter->sgi_vm, &errmsg); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to destroy a VM (%s)", + NULL_MSGCHK(errmsg)); + } + + smb_lgrp_db_close(iter->sgi_db); +} + +/* + * smb_lgrp_iterate + * + * Iterate through group database + * Group information is returned in provided group structure. + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +int +smb_lgrp_iterate(smb_giter_t *iter, smb_group_t *grp) +{ + const char **values; + int ncol; + int rc; + int i; + + if (iter->sgi_vm == NULL || iter->sgi_db == NULL) + return (SMB_LGRP_INVALID_ARG); + + bzero(grp, sizeof (smb_group_t)); + rc = sqlite_step(iter->sgi_vm, &ncol, &values, NULL); + if (rc == SQLITE_DONE) + return (SMB_LGRP_NO_MORE); + + if (rc != SQLITE_ROW) + return (SMB_LGRP_DBEXEC_FAILED); + + if (ncol != SMB_LGRP_GTBL_NCOL) + return (SMB_LGRP_DB_ERROR); + + for (i = 0; i < ncol; i++) { + if (values[i] == NULL) + return (SMB_LGRP_DB_ERROR); + } + + return (smb_lgrp_decode(grp, (char **)values, SMB_LGRP_INFO_ALL, + iter->sgi_db)); +} + +/* + * smb_lgrp_is_member + * + * Check to see if the specified account is a member of + * the given group. + */ +boolean_t +smb_lgrp_is_member(smb_group_t *grp, nt_sid_t *sid) +{ + int i; + + if (grp == NULL || grp->sg_members == NULL || sid == NULL) + return (B_FALSE); + + for (i = 0; i < grp->sg_nmembers; i++) { + if (nt_sid_is_equal(grp->sg_members[i].gs_sid, sid)) + return (B_TRUE); + } + + return (B_FALSE); +} + +/* + * smb_lgrp_strerror + * + * Returns a text for the given group error code. + */ +char * +smb_lgrp_strerror(int errno) +{ + switch (errno) { + case SMB_LGRP_SUCCESS: + return (dgettext(TEXT_DOMAIN, "success")); + case SMB_LGRP_INVALID_ARG: + return (dgettext(TEXT_DOMAIN, "invalid argument")); + case SMB_LGRP_INVALID_MEMBER: + return (dgettext(TEXT_DOMAIN, "invalid member type")); + case SMB_LGRP_INVALID_NAME: + return (dgettext(TEXT_DOMAIN, "invalid name")); + case SMB_LGRP_NOT_FOUND: + return (dgettext(TEXT_DOMAIN, "group not found")); + case SMB_LGRP_EXISTS: + return (dgettext(TEXT_DOMAIN, "group exists")); + case SMB_LGRP_NO_SID: + return (dgettext(TEXT_DOMAIN, "cannot obtain a SID")); + case SMB_LGRP_NO_LOCAL_SID: + return (dgettext(TEXT_DOMAIN, "cannot get the machine SID")); + case SMB_LGRP_SID_NOTLOCAL: + return (dgettext(TEXT_DOMAIN, "not a local SID")); + case SMB_LGRP_WKSID: + return (dgettext(TEXT_DOMAIN, + "operation not permitted on well-known accounts")); + case SMB_LGRP_NO_MEMORY: + return (dgettext(TEXT_DOMAIN, "not enough memory")); + case SMB_LGRP_DB_ERROR: + return (dgettext(TEXT_DOMAIN, "database operation error")); + case SMB_LGRP_DBINIT_ERROR: + return (dgettext(TEXT_DOMAIN, "database initialization error")); + case SMB_LGRP_INTERNAL_ERROR: + return (dgettext(TEXT_DOMAIN, "internal error")); + case SMB_LGRP_MEMBER_IN_GROUP: + return (dgettext(TEXT_DOMAIN, "member already in the group")); + case SMB_LGRP_MEMBER_NOT_IN_GROUP: + return (dgettext(TEXT_DOMAIN, "not a member")); + case SMB_LGRP_NO_SUCH_PRIV: + return (dgettext(TEXT_DOMAIN, "no such privilege")); + case SMB_LGRP_NO_SUCH_DOMAIN: + return (dgettext(TEXT_DOMAIN, "no such domain SID")); + case SMB_LGRP_PRIV_HELD: + return (dgettext(TEXT_DOMAIN, "already holds the privilege")); + case SMB_LGRP_PRIV_NOT_HELD: + return (dgettext(TEXT_DOMAIN, "privilege not held")); + case SMB_LGRP_BAD_DATA: + return (dgettext(TEXT_DOMAIN, "bad data")); + case SMB_LGRP_NO_MORE: + return (dgettext(TEXT_DOMAIN, "no more groups")); + case SMB_LGRP_DBOPEN_FAILED: + return (dgettext(TEXT_DOMAIN, "failed openning database")); + case SMB_LGRP_DBEXEC_FAILED: + return (dgettext(TEXT_DOMAIN, + "failed executing database operation")); + case SMB_LGRP_DBINIT_FAILED: + return (dgettext(TEXT_DOMAIN, "failed initializing database")); + case SMB_LGRP_DOMLKP_FAILED: + return (dgettext(TEXT_DOMAIN, "failed getting the domain SID")); + case SMB_LGRP_DOMINS_FAILED: + return (dgettext(TEXT_DOMAIN, + "failed inserting the domain SID")); + case SMB_LGRP_INSERT_FAILED: + return (dgettext(TEXT_DOMAIN, "failed inserting the group")); + case SMB_LGRP_DELETE_FAILED: + return (dgettext(TEXT_DOMAIN, "failed deleting the group")); + case SMB_LGRP_UPDATE_FAILED: + return (dgettext(TEXT_DOMAIN, "failed updating the group")); + case SMB_LGRP_LOOKUP_FAILED: + return (dgettext(TEXT_DOMAIN, "failed looking up the group")); + } + + return (dgettext(TEXT_DOMAIN, "unknown error code")); +} + +/* + * smb_lgrp_chkmember + * + * Determines valid account types for being member of + * a local group. + * + * Currently, we just support users as valid members. + */ +static boolean_t +smb_lgrp_chkmember(uint16_t sid_type) +{ + return (sid_type == SidTypeUser); +} + +/* + * smb_lgrp_start + * + * Initializes the library private global variables. + * If the database doesn't exist, it'll create it and adds the + * predefined builtin groups. + */ +int +smb_lgrp_start(void) +{ + char *supported_bg[] = + {"Administrators", "Backup Operators", "Power Users"}; + well_known_account_t *wka; + int rc, i, ngrp; + char *lsid_str; + + (void) mutex_init(&smb_lgrp_lsid_mtx, USYNC_THREAD, NULL); + (void) mutex_lock(&smb_lgrp_lsid_mtx); + lsid_str = smb_config_get_localsid(); + if (lsid_str == NULL) { + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (SMB_LGRP_NO_LOCAL_SID); + } + + smb_lgrp_lsid = nt_sid_strtosid(lsid_str); + free(lsid_str); + if (!nt_sid_is_valid(smb_lgrp_lsid)) { + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (SMB_LGRP_NO_LOCAL_SID); + } + + rc = smb_lgrp_db_init(); + if (rc != SMB_LGRP_SUCCESS) { + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + return (rc); + } + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + + ngrp = sizeof (supported_bg) / sizeof (supported_bg[0]); + for (i = 0; i < ngrp; i++) { + wka = nt_builtin_lookup(supported_bg[i]); + if (wka == NULL) + continue; + rc = smb_lgrp_add(wka->name, wka->desc); + if (rc != SMB_LGRP_SUCCESS) + syslog(LOG_DEBUG, "failed to add %s", wka->name); + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_stop + * + * Unintialize the library global private variables. + */ +void +smb_lgrp_stop(void) +{ + (void) mutex_lock(&smb_lgrp_lsid_mtx); + free(smb_lgrp_lsid); + smb_lgrp_lsid = NULL; + (void) mutex_unlock(&smb_lgrp_lsid_mtx); + (void) mutex_destroy(&smb_lgrp_lsid_mtx); +} + +/* + * smb_lgrp_db_open + * + * Opens group database with the given mode. + */ +static sqlite * +smb_lgrp_db_open(int mode) +{ + sqlite *db; + char *errmsg = NULL; + + db = sqlite_open(SMB_LGRP_DB_NAME, mode, &errmsg); + if (db == NULL) { + syslog(LOG_ERR, "failed to open group database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + return (db); +} + +/* + * smb_lgrp_db_close + * + * Closes the given database handle + */ +static void +smb_lgrp_db_close(sqlite *db) +{ + if (db) { + sqlite_close(db); + } +} + +/* + * smb_lgrp_db_init + * + * Creates the group database based on the defined SQL statement. + * It also initializes db_info and domain tables. + */ +static int +smb_lgrp_db_init(void) +{ + int dbrc = SQLITE_OK; + int rc = SMB_LGRP_SUCCESS; + sqlite *db = NULL; + char *errmsg = NULL; + + db = sqlite_open(SMB_LGRP_DB_NAME, 0600, &errmsg); + if (db == NULL) { + syslog(LOG_ERR, "failed to create group database (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DBOPEN_FAILED); + } + + sqlite_busy_timeout(db, SMB_LGRP_DB_TIMEOUT); + dbrc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); + if (dbrc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to begin database transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + sqlite_close(db); + return (SMB_LGRP_DBEXEC_FAILED); + } + + switch (sqlite_exec(db, SMB_LGRP_DB_SQL, NULL, NULL, &errmsg)) { + case SQLITE_ERROR: + /* + * This is the normal situation: CREATE probably failed because + * tables already exist. It may indicate an error in SQL as well + * but we cannot tell. + */ + sqlite_freemem(errmsg); + dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + rc = SMB_LGRP_SUCCESS; + break; + + case SQLITE_OK: + dbrc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, + &errmsg); + if (dbrc != SQLITE_OK) + break; + rc = smb_lgrp_dtbl_insert(db, NT_BUILTIN_DOMAIN_SIDSTR, + NULL); + if (rc == SMB_LGRP_SUCCESS) + rc = smb_lgrp_db_setinfo(db); + if (rc != SMB_LGRP_SUCCESS) { + (void) sqlite_close(db); + (void) unlink(SMB_LGRP_DB_NAME); + return (rc); + } + break; + + default: + syslog(LOG_ERR, + "failed to initialize group database (%s)", errmsg); + sqlite_freemem(errmsg); + dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, + &errmsg); + rc = SMB_LGRP_DBINIT_FAILED; + break; + } + + if (dbrc != SQLITE_OK) { + /* this is bad - database may be left in a locked state */ + syslog(LOG_DEBUG, "failed to close a transaction (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + } + + (void) sqlite_close(db); + return (rc); +} + +/* + * smb_lgrp_gtbl_lookup + * + * This is a flexible lookup function for the group database. + * The key type can be specified by the 'key' arg and the actual key + * values can be passed after the 'infolvl' arg. 'infolvl' arg specifies + * what information items for the specified group is needed. + * + * Note that the function assumes the given key is unique and only + * specifies one or 0 group. The keys that are supported now are + * the group name and the group SID + * + * Note that this function doesn't allocate the group + * structure itself only the fields, so the given grp + * pointer has to point to a group structure. + * Caller must free the allocated memories for the fields + * by calling smb_lgrp_free(). + */ +static int +smb_lgrp_gtbl_lookup(sqlite *db, int key, smb_group_t *grp, int infolvl, ...) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc, dom_idx; + smb_group_t kgrp; + va_list ap; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + bzero(grp, sizeof (smb_group_t)); + va_start(ap, infolvl); + + switch (key) { + case SMB_LGRP_GTBL_NAME: + kgrp.sg_name = va_arg(ap, char *); + sql = sqlite_mprintf("SELECT * FROM groups WHERE name = '%s'", + kgrp.sg_name); + break; + + case SMB_LGRP_GTBL_SIDRID: + kgrp.sg_rid = va_arg(ap, uint32_t); + kgrp.sg_domain = va_arg(ap, smb_gdomain_t); + dom_idx = (kgrp.sg_domain == SMB_LGRP_LOCAL) + ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; + sql = sqlite_mprintf("SELECT * FROM groups" + "WHERE (sid_idx = %d) AND (sid_rid = %u)", + dom_idx, kgrp.sg_rid); + break; + + default: + va_end(ap); + return (SMB_LGRP_INVALID_ARG); + } + + va_end(ap); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != SMB_LGRP_GTBL_NCOL) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + rc = smb_lgrp_decode(grp, &result[SMB_LGRP_GTBL_NCOL], infolvl, db); + sqlite_free_table(result); + return (rc); +} + +/* + * smb_lgrp_gtbl_exists + * + * Checks to see if the given group exists or not. + */ +static boolean_t +smb_lgrp_gtbl_exists(sqlite *db, char *gname) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + if (db == NULL) + return (NULL); + + sql = sqlite_mprintf("SELECT name FROM groups WHERE name = '%s'", + gname); + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (B_FALSE); + } + + sqlite_free_table(result); + return (nrow != 0); +} + +/* + * smb_lgrp_gtbl_count + * + * Counts the number of groups in the domain specified by + * 'dom_idx' + */ +static int +smb_lgrp_gtbl_count(sqlite *db, int dom_idx, int *count) +{ + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + *count = 0; + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT sid_idx FROM groups WHERE sid_idx = %d", + dom_idx); + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to count (%s)", NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + sqlite_free_table(result); + if (ncol != 1) + return (SMB_LGRP_DB_ERROR); + + *count = nrow; + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_gtbl_insert + * + * Insert a record for the given group in the group database. + * + * NOTE: this function assumes that this group has no members + * at this time. + */ +static int +smb_lgrp_gtbl_insert(sqlite *db, smb_group_t *grp) +{ + smb_lgpid_t privs[SE_MAX_LUID + 1]; + smb_lgplist_t plist; + char *errmsg = NULL; + char *sql; + int dom_idx; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + dom_idx = (grp->sg_domain == SMB_LGRP_LOCAL) + ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; + + plist.p_cnt = SE_MAX_LUID; + plist.p_ids = privs; + smb_lgrp_encode_privset(grp, &plist); + + sql = sqlite_mprintf("INSERT INTO groups" + "(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, " + "n_privs, privs, n_members, members) " + "VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')", + grp->sg_name, dom_idx, grp->sg_rid, grp->sg_id.gs_type, + grp->sg_attr, (grp->sg_cmnt) ? grp->sg_cmnt : "", + plist.p_cnt, (char *)plist.p_ids, 0, ""); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert %s (%s)", + grp->sg_name, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_INSERT_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_delete + * + * Removes the specified group from the database + */ +static int +smb_lgrp_gtbl_delete(sqlite *db, char *gname) +{ + char *errmsg = NULL; + char *sql; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("DELETE FROM groups WHERE name = '%s'", gname); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to delete %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_DELETE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update + * + * Updates the specified group information, the supported items + * are group name and comment + */ +static int +smb_lgrp_gtbl_update(sqlite *db, char *gname, smb_group_t *grp, int col_id) +{ + char *errmsg = NULL; + char *sql; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + /* UPDATE doesn't fail if gname doesn't exist */ + if (!smb_lgrp_gtbl_exists(db, gname)) + return (SMB_LGRP_NOT_FOUND); + + switch (col_id) { + case SMB_LGRP_GTBL_NAME: + if (smb_lgrp_gtbl_exists(db, grp->sg_name)) + return (SMB_LGRP_EXISTS); + sql = sqlite_mprintf("UPDATE groups SET name = '%s' " + "WHERE name = '%s'", grp->sg_name, gname); + break; + + case SMB_LGRP_GTBL_CMNT: + sql = sqlite_mprintf("UPDATE groups SET comment = '%q' " + "WHERE name = '%s'", grp->sg_cmnt, gname); + break; + + default: + return (SMB_LGRP_INVALID_ARG); + } + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update_mlist + * + * Adds/removes the specified member from the member list of the + * given group + */ +static int +smb_lgrp_gtbl_update_mlist(sqlite *db, char *gname, smb_gsid_t *member, + int flags) +{ + smb_lgmlist_t new_members; + smb_lgmlist_t members; + smb_lgmid_t mid; + char *errmsg = NULL; + char *sql; + char **result; + int nrow, ncol; + int rc; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT n_members, members FROM groups " + "WHERE name = '%s'", gname); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != 2) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + bzero(&mid, sizeof (mid)); + mid.m_type = member->gs_type; + rc = smb_lgrp_dtbl_getidx(db, member->gs_sid, mid.m_type, + &mid.m_idx, &mid.m_rid); + if (rc != SMB_LGRP_SUCCESS) { + sqlite_free_table(result); + return (rc); + } + + members.m_cnt = atoi(result[2]); + members.m_ids = result[3]; + + switch (flags) { + case SMB_LGRP_DB_ADDMEMBER: + rc = smb_lgrp_mlist_add(&members, &mid, &new_members); + break; + case SMB_LGRP_DB_DELMEMBER: + rc = smb_lgrp_mlist_del(&members, &mid, &new_members); + break; + default: + rc = SMB_LGRP_INVALID_ARG; + } + + sqlite_free_table(result); + if (rc != SMB_LGRP_SUCCESS) + return (rc); + + sql = sqlite_mprintf("UPDATE groups SET n_members = %u, members = '%s'" + " WHERE name = '%s'", new_members.m_cnt, new_members.m_ids, gname); + + free(new_members.m_ids); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", gname, + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_gtbl_update_plist + * + * Adds/removes the specified privilege from the privilege list of the + * given group + */ +static int +smb_lgrp_gtbl_update_plist(sqlite *db, char *gname, uint8_t priv_id, + boolean_t enable) +{ + char *sql; + char *errmsg = NULL; + char **result; + int nrow, ncol; + int rc; + smb_lgplist_t privs; + smb_lgplist_t new_privs; + + if (db == NULL) + return (SMB_LGRP_DBOPEN_FAILED); + + sql = sqlite_mprintf("SELECT n_privs, privs FROM groups " + "WHERE name = '%s'", gname); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_LOOKUP_FAILED); + } + + if (nrow == 0) { + /* group not found */ + sqlite_free_table(result); + return (SMB_LGRP_NOT_FOUND); + } + + if (nrow != 1 || ncol != 2) { + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); + } + + privs.p_cnt = atoi(result[2]); + privs.p_ids = (smb_lgpid_t *)result[3]; + + if (enable) + rc = smb_lgrp_plist_add(&privs, priv_id, &new_privs); + else + rc = smb_lgrp_plist_del(&privs, priv_id, &new_privs); + + sqlite_free_table(result); + if (rc != SMB_LGRP_SUCCESS) + return (rc); + + sql = sqlite_mprintf("UPDATE groups SET n_privs = %u, privs = '%q'" + " WHERE name = '%s'", new_privs.p_cnt, (char *)new_privs.p_ids, + gname); + + free(new_privs.p_ids); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to update %s (%s)", + gname, NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_UPDATE_FAILED; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_dtbl_insert + * + * Inserts the specified domain SID in the dmain table. + * Upon successful insert the index will be returned in + * 'dom_idx' arg. + */ +static int +smb_lgrp_dtbl_insert(sqlite *db, char *dom_sid, uint32_t *dom_idx) +{ + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("INSERT INTO domains (dom_sid, dom_cnt)" + " VALUES('%s', 1);", dom_sid); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert domain SID (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMINS_FAILED); + } + + if (dom_idx) + *dom_idx = sqlite_last_insert_rowid(db); + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_dtbl_getidx + * + * Searches the domain table for the domain SID of the + * given member SID. If it finds the domain SID it'll + * return the index and the RID, otherwise it'll insert + * it in the domain table as a new SID. + */ +static int +smb_lgrp_dtbl_getidx(sqlite *db, nt_sid_t *sid, uint16_t sid_type, + uint32_t *dom_idx, uint32_t *rid) +{ + char sidstr[NT_SID_FMTBUF_SIZE]; + nt_sid_t *dom_sid; + char **result; + int nrow, ncol; + char *errmsg = NULL; + char *sql; + int rc; + + if (nt_sid_is_indomain(smb_lgrp_lsid, sid)) { + /* This is a local SID */ + int id_type = (sid_type == SidTypeUser) + ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; + *dom_idx = SMB_LGRP_LOCAL_IDX; + if (smb_idmap_getid(sid, rid, &id_type) != IDMAP_SUCCESS) + return (SMB_LGRP_INTERNAL_ERROR); + } + + dom_sid = nt_sid_dup(sid); + if (dom_sid == NULL) + return (SMB_LGRP_NO_MEMORY); + + (void) nt_sid_split(dom_sid, rid); + nt_sid_format2(dom_sid, sidstr); + free(dom_sid); + + sql = sqlite_mprintf("SELECT dom_idx FROM domains WHERE dom_sid = '%s'", + sidstr); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup domain SID (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMLKP_FAILED); + } + + switch (nrow) { + case 0: + /* new domain SID; insert it into the domains table */ + sqlite_free_table(result); + return (smb_lgrp_dtbl_insert(db, sidstr, dom_idx)); + + case 1: + *dom_idx = atoi(result[1]); + sqlite_free_table(result); + return (SMB_LGRP_SUCCESS); + } + + sqlite_free_table(result); + return (SMB_LGRP_DB_ERROR); +} + +/* + * smb_lgrp_dtbl_getsid + * + * Searchs the domain table for the given domain index. + * Converts the found domain SID to binary format and + * returns it in the 'sid' arg. + * + * Caller must free the returned SID by calling free(). + */ +static int +smb_lgrp_dtbl_getsid(sqlite *db, uint32_t dom_idx, nt_sid_t **sid) +{ + char **result; + int nrow, ncol; + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("SELECT dom_sid FROM domains WHERE dom_idx = %u", + dom_idx); + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); + sqlite_freemem(sql); + + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to lookup domain index (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + return (SMB_LGRP_DOMLKP_FAILED); + } + + switch (nrow) { + case 0: + rc = SMB_LGRP_NO_SUCH_DOMAIN; + break; + + case 1: + *sid = nt_sid_strtosid(result[1]); + rc = (*sid == NULL) + ? SMB_LGRP_INTERNAL_ERROR : SMB_LGRP_SUCCESS; + break; + + default: + rc = SMB_LGRP_DB_ERROR; + break; + } + + sqlite_free_table(result); + return (rc); +} + +/* + * smb_lgrp_db_setinfo + * + * Initializes the db_info table upon database creation. + */ +static int +smb_lgrp_db_setinfo(sqlite *db) +{ + char *errmsg = NULL; + char *sql; + int rc; + + sql = sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor," + " magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR, + SMB_LGRP_DB_VERMINOR, SMB_LGRP_DB_MAGIC); + + if (sql == NULL) + return (SMB_LGRP_NO_MEMORY); + + rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); + sqlite_freemem(sql); + if (rc != SQLITE_OK) { + syslog(LOG_DEBUG, "failed to insert database information (%s)", + NULL_MSGCHK(errmsg)); + sqlite_freemem(errmsg); + rc = SMB_LGRP_DBINIT_ERROR; + } else { + rc = SMB_LGRP_SUCCESS; + } + + return (rc); +} + +/* + * smb_lgrp_mlist_add + * + * Adds the given member (newm) to the input member list (in_members) + * if it's not already there. The result list will be returned in + * out_members. The caller must free the allocated memory for + * out_members by calling free(). + * + * in_members and out_members are hex strings. + */ +static int +smb_lgrp_mlist_add(smb_lgmlist_t *in_members, smb_lgmid_t *newm, + smb_lgmlist_t *out_members) +{ + char mid_hex[SMB_LGRP_MID_HEXSZ]; + char *in_list; + char *out_list; + int in_size; + int out_size; + int mid_hexsz; + int i; + + out_members->m_cnt = 0; + out_members->m_ids = NULL; + + bzero(mid_hex, sizeof (mid_hex)); + mid_hexsz = bintohex((const char *)newm, sizeof (smb_lgmid_t), + mid_hex, sizeof (mid_hex)); + + /* + * Check to see if this is already a group member + */ + in_list = in_members->m_ids; + for (i = 0; i < in_members->m_cnt; i++) { + if (strncmp(in_list, mid_hex, mid_hexsz) == 0) + return (SMB_LGRP_MEMBER_IN_GROUP); + in_list += mid_hexsz; + } + + in_size = (in_members->m_ids) ? strlen(in_members->m_ids) : 0; + out_size = in_size + sizeof (mid_hex) + 1; + out_list = malloc(out_size); + if (out_list == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(out_list, out_size); + if (in_members->m_ids) + (void) strlcpy(out_list, in_members->m_ids, out_size); + (void) strcat(out_list, mid_hex); + + out_members->m_cnt = in_members->m_cnt + 1; + out_members->m_ids = out_list; + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_mlist_del + * + * Removes the given member (msid) from the input member list + * (in_members) if it's already there. The result list will b + * returned in out_members. The caller must free the allocated + * memory for out_members by calling free(). + * + * in_members and out_members are hex strings. + */ +static int +smb_lgrp_mlist_del(smb_lgmlist_t *in_members, smb_lgmid_t *mid, + smb_lgmlist_t *out_members) +{ + char mid_hex[SMB_LGRP_MID_HEXSZ]; + char *in_list; + char *out_list; + int in_size; + int out_size; + int mid_hexsz; + int out_cnt; + int i; + + out_members->m_cnt = 0; + out_members->m_ids = NULL; + + if ((in_members == NULL) || (in_members->m_cnt == 0)) + return (SMB_LGRP_MEMBER_NOT_IN_GROUP); + + in_size = strlen(in_members->m_ids); + out_size = in_size + sizeof (mid_hex) + 1; + out_list = malloc(out_size); + if (out_list == NULL) + return (SMB_LGRP_NO_MEMORY); + + *out_list = '\0'; + + bzero(mid_hex, sizeof (mid_hex)); + mid_hexsz = bintohex((const char *)mid, sizeof (smb_lgmid_t), + mid_hex, sizeof (mid_hex)); + + in_list = in_members->m_ids; + for (i = 0, out_cnt = 0; i < in_members->m_cnt; i++) { + if (strncmp(in_list, mid_hex, mid_hexsz)) { + (void) strncat(out_list, in_list, mid_hexsz); + out_cnt++; + } + in_list += mid_hexsz; + } + + if (out_cnt == in_members->m_cnt) { + free(out_list); + return (SMB_LGRP_MEMBER_NOT_IN_GROUP); + } + + out_members->m_cnt = out_cnt; + out_members->m_ids = out_list; + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_plist_add + * + * Adds the given privilege to the input list (in_privs) + * if it's not already there. The result list is returned + * in out_privs. The caller must free the allocated memory + * for out_privs by calling free(). + */ +static int +smb_lgrp_plist_add(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, + smb_lgplist_t *out_privs) +{ + int i, size; + smb_lgpid_t *pbuf; + + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + + for (i = 0; i < in_privs->p_cnt; i++) { + if (in_privs->p_ids[i] == priv_id) + return (SMB_LGRP_PRIV_HELD); + } + + size = (in_privs->p_cnt + 1) * sizeof (smb_lgpid_t) + 1; + pbuf = malloc(size); + if (pbuf == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(pbuf, size); + bcopy(in_privs->p_ids, pbuf, in_privs->p_cnt * sizeof (smb_lgpid_t)); + pbuf[in_privs->p_cnt] = priv_id; + + out_privs->p_cnt = in_privs->p_cnt + 1; + out_privs->p_ids = pbuf; + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_plist_del + * + * Removes the given privilege from the input list (in_privs) + * if it's already there. The result list is returned + * in out_privs. The caller must free the allocated memory + * for out_privs by calling free(). + */ +static int +smb_lgrp_plist_del(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, + smb_lgplist_t *out_privs) +{ + int i, size; + + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + + if ((in_privs == NULL) || (in_privs->p_cnt == 0)) + return (SMB_LGRP_PRIV_NOT_HELD); + + size = (in_privs->p_cnt - 1) * sizeof (smb_lgpid_t) + 1; + out_privs->p_ids = malloc(size); + if (out_privs->p_ids == NULL) + return (SMB_LGRP_NO_MEMORY); + + bzero(out_privs->p_ids, size); + + for (i = 0; i < in_privs->p_cnt; i++) { + if (in_privs->p_ids[i] != priv_id) + out_privs->p_ids[out_privs->p_cnt++] = + in_privs->p_ids[i]; + } + + if (out_privs->p_cnt == in_privs->p_cnt) { + free(out_privs->p_ids); + out_privs->p_cnt = 0; + out_privs->p_ids = NULL; + return (SMB_LGRP_PRIV_NOT_HELD); + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_encode_privset + * + * Encodes given privilege set into a buffer to be stored in the group + * database. Each entry of the encoded buffer contains the privilege ID + * of an enable privilege. The returned buffer is null-terminated. + */ +static void +smb_lgrp_encode_privset(smb_group_t *grp, smb_lgplist_t *plist) +{ + smb_privset_t *privs; + uint32_t pcnt = plist->p_cnt; + int i; + + bzero(plist->p_ids, sizeof (smb_lgpid_t) * plist->p_cnt); + plist->p_cnt = 0; + + privs = grp->sg_privs; + if ((privs == NULL) || (privs->priv_cnt == 0)) + return; + + if (pcnt < privs->priv_cnt) { + assert(0); + } + + for (i = 0; i < privs->priv_cnt; i++) { + if (privs->priv[i].attrs == SE_PRIVILEGE_ENABLED) { + plist->p_ids[plist->p_cnt++] = + (uint8_t)privs->priv[i].luid.lo_part; + } + } +} + +/* + * smb_lgrp_decode_privset + * + * Decodes the privilege information read from group table + * (nprivs, privs) into a binray format specified by the + * privilege field of smb_group_t + */ +static int +smb_lgrp_decode_privset(smb_group_t *grp, char *nprivs, char *privs) +{ + smb_lgplist_t plist; + int i; + + plist.p_cnt = atoi(nprivs); + if (strlen(privs) != plist.p_cnt) + return (SMB_LGRP_BAD_DATA); + + plist.p_ids = (smb_lgpid_t *)privs; + grp->sg_privs = smb_privset_new(); + if (grp->sg_privs == NULL) + return (SMB_LGRP_NO_MEMORY); + + for (i = 0; i < plist.p_cnt; i++) + smb_privset_enable(grp->sg_privs, plist.p_ids[i]); + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_decode_members + * + * Decodes the members information read from group table + * (nmembers, members) into a binray format specified by the + * member fields of smb_group_t + */ +static int +smb_lgrp_decode_members(smb_group_t *grp, char *nmembers, char *members, + sqlite *db) +{ + smb_lgmid_t *m_ids; + smb_lgmid_t *mid; + smb_gsid_t *member; + int mids_size; + int i, rc; + + grp->sg_nmembers = atoi(nmembers); + mids_size = grp->sg_nmembers * sizeof (smb_lgmid_t); + m_ids = malloc(mids_size); + if (m_ids == NULL) + return (SMB_LGRP_NO_MEMORY); + + grp->sg_members = malloc(grp->sg_nmembers * sizeof (smb_gsid_t)); + if (grp->sg_members == NULL) { + free(m_ids); + return (SMB_LGRP_NO_MEMORY); + } + + (void) hextobin(members, strlen(members), (char *)m_ids, mids_size); + + mid = m_ids; + member = grp->sg_members; + for (i = 0; i < grp->sg_nmembers; i++, mid++, member++) { + rc = smb_lgrp_getsid(mid->m_idx, &mid->m_rid, mid->m_type, db, + &member->gs_sid); + if (rc != SMB_LGRP_SUCCESS) { + free(m_ids); + return (SMB_LGRP_DB_ERROR); + } + + member->gs_type = mid->m_type; + } + + free(m_ids); + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_decode + * + * Fills out the fields of the given group (grp) based in the + * string information read from the group table. infolvl determines + * which fields are requested and need to be decoded. + * + * Allocated memories must be freed by calling smb_lgrp_free() + * upon successful return. + */ +static int +smb_lgrp_decode(smb_group_t *grp, char **values, int infolvl, sqlite *db) +{ + uint32_t sid_idx; + int rc; + + if (infolvl == SMB_LGRP_INFO_NONE) + return (SMB_LGRP_SUCCESS); + + if (infolvl & SMB_LGRP_INFO_NAME) { + grp->sg_name = strdup(values[SMB_LGRP_GTBL_NAME]); + if (grp->sg_name == NULL) + return (SMB_LGRP_NO_MEMORY); + } + + if (infolvl & SMB_LGRP_INFO_CMNT) { + grp->sg_cmnt = strdup(values[SMB_LGRP_GTBL_CMNT]); + if (grp->sg_cmnt == NULL) { + smb_lgrp_free(grp); + return (SMB_LGRP_NO_MEMORY); + } + } + + + if (infolvl & SMB_LGRP_INFO_SID) { + sid_idx = atoi(values[SMB_LGRP_GTBL_SIDIDX]); + grp->sg_rid = atoi(values[SMB_LGRP_GTBL_SIDRID]); + grp->sg_attr = atoi(values[SMB_LGRP_GTBL_SIDATR]); + grp->sg_id.gs_type = atoi(values[SMB_LGRP_GTBL_SIDTYP]); + rc = smb_lgrp_getsid(sid_idx, &grp->sg_rid, grp->sg_id.gs_type, + db, &grp->sg_id.gs_sid); + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (SMB_LGRP_NO_MEMORY); + } + grp->sg_domain = (sid_idx == SMB_LGRP_LOCAL_IDX) + ? SMB_LGRP_LOCAL : SMB_LGRP_BUILTIN; + } + + if (infolvl & SMB_LGRP_INFO_PRIV) { + rc = smb_lgrp_decode_privset(grp, values[SMB_LGRP_GTBL_NPRIVS], + values[SMB_LGRP_GTBL_PRIVS]); + + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (rc); + } + } + + if (infolvl & SMB_LGRP_INFO_MEMB) { + rc = smb_lgrp_decode_members(grp, values[SMB_LGRP_GTBL_NMEMBS], + values[SMB_LGRP_GTBL_MEMBS], db); + if (rc != SMB_LGRP_SUCCESS) { + smb_lgrp_free(grp); + return (rc); + } + } + + return (SMB_LGRP_SUCCESS); +} + +/* + * smb_lgrp_chkname + * + * User account names are limited to 20 characters and group names are + * limited to 256 characters. In addition, account names cannot be terminated + * by a period and they cannot include commas or any of the following printable + * characters: ", /, \, [, ], :, |, <, >, +, =, ;, ?, *. + * Names also cannot include characters in the range 1-31, which are + * nonprintable. + * + * Source: MSDN, description of NetLocalGroupAdd function. + */ +static boolean_t +smb_lgrp_chkname(char *name) +{ + static char *invalid_chars = + "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" + "\020\021\022\023\024\025\026\027\030\031" + "\"/\\[]:|<>+=;,*?"; + int len, i; + + if (name == NULL || *name == '\0') + return (B_FALSE); + + len = strlen(name); + if (len > SMB_LGRP_NAME_MAX) + return (B_FALSE); + + if (name[len - 1] == '.') + return (B_FALSE); + + for (i = 0; i < len; i++) + if (strchr(invalid_chars, name[i])) + return (B_FALSE); + + (void) utf8_strlwr(name); + return (B_TRUE); +} + +/* + * smb_lgrp_set_default_privs + * + * set default privileges for Administrators and Backup Operators + */ +static void +smb_lgrp_set_default_privs(smb_group_t *grp) +{ + if (utf8_strcasecmp(grp->sg_name, "Administrators") == 0) { + smb_privset_enable(grp->sg_privs, SE_TAKE_OWNERSHIP_LUID); + return; + } + + if (utf8_strcasecmp(grp->sg_name, "Backup Operators") == 0) { + smb_privset_enable(grp->sg_privs, SE_BACKUP_LUID); + smb_privset_enable(grp->sg_privs, SE_RESTORE_LUID); + return; + } +} + +/* + * smb_lgrp_getsid + * + * Returns a SID based on the provided information + * If dom_idx is 0, it means 'rid' contains a UID/GID and the + * returned SID will be a local SID. If dom_idx is not 0 then + * the domain SID will be fetched from the domain table. + */ +static int +smb_lgrp_getsid(int dom_idx, uint32_t *rid, uint16_t sid_type, + sqlite *db, nt_sid_t **sid) +{ + nt_sid_t *dom_sid = NULL; + nt_sid_t *res_sid = NULL; + int id_type; + int rc; + + *sid = NULL; + if (dom_idx == SMB_LGRP_LOCAL_IDX) { + id_type = (sid_type == SidTypeUser) + ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; + if (smb_idmap_getsid(*rid, id_type, &res_sid) != IDMAP_SUCCESS) + return (SMB_LGRP_NO_SID); + + /* + * Make sure the returned SID is local + */ + if (!nt_sid_is_indomain(smb_lgrp_lsid, res_sid)) { + free(res_sid); + return (SMB_LGRP_SID_NOTLOCAL); + } + + (void) nt_sid_get_rid(res_sid, rid); + *sid = res_sid; + return (SMB_LGRP_SUCCESS); + } + + rc = smb_lgrp_dtbl_getsid(db, dom_idx, &dom_sid); + if (rc != SMB_LGRP_SUCCESS) + return (SMB_LGRP_DB_ERROR); + + res_sid = nt_sid_splice(dom_sid, *rid); + free(dom_sid); + if (res_sid == NULL) + return (SMB_LGRP_NO_MEMORY); + + *sid = res_sid; + return (SMB_LGRP_SUCCESS); +} diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c b/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c index ce7cef198a..be8853f4bc 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,9 +41,6 @@ #include <smbsrv/libsmb.h> #include <smbsrv/smb_privilege.h> -#define SMB_PRIV_MIN 2 -#define SMB_PRIV_MAX 24 - static char *smb_priv_getname(uint32_t id); /* @@ -98,7 +95,7 @@ smb_priv_presentable_num() int i, num; num = 0; - for (i = SMB_PRIV_MIN; i <= SMB_PRIV_MAX; i++) + for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++) if (priv_table[i].flags == PF_PRESENTABLE) num++; @@ -119,7 +116,7 @@ smb_priv_presentable_ids(uint32_t *ids, int num) if (ids == NULL || num <= 0) return (0); - for (i = SMB_PRIV_MIN, j = 0; i <= SMB_PRIV_MAX; i++) + for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++) if (priv_table[i].flags == PF_PRESENTABLE) ids[j++] = priv_table[i].id; @@ -135,7 +132,7 @@ smb_priv_presentable_ids(uint32_t *ids, int num) smb_privinfo_t * smb_priv_getbyvalue(uint32_t id) { - if (id < SMB_PRIV_MIN || id > SMB_PRIV_MAX) + if (id < SE_MIN_LUID || id > SE_MAX_LUID) return (0); return (&priv_table[id]); @@ -157,7 +154,7 @@ smb_priv_getbyname(char *name) if (name == 0) return (0); - for (i = SMB_PRIV_MIN; i <= SMB_PRIV_MAX; ++i) { + for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) { entry = &priv_table[i]; if (utf8_strcasecmp(name, entry->name) == 0) @@ -176,7 +173,7 @@ smb_priv_getbyname(char *name) int smb_privset_size() { - int pcnt = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1; return (2 * sizeof (uint32_t) + pcnt * sizeof (smb_luid_attrs_t)); @@ -198,7 +195,7 @@ smb_privset_validate(smb_privset_t *privset) return (0); } - count = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + count = SE_MAX_LUID - SE_MIN_LUID + 1; if (privset->priv_cnt != count) { return (0); @@ -210,7 +207,7 @@ smb_privset_validate(smb_privset_t *privset) } if (privset->priv[i].luid.lo_part != - i + SMB_PRIV_MIN) { + i + SE_MIN_LUID) { return (0); } } @@ -232,13 +229,13 @@ smb_privset_init(smb_privset_t *privset) if (privset == 0) return; - count = SMB_PRIV_MAX - SMB_PRIV_MIN + 1; + count = SE_MAX_LUID - SE_MIN_LUID + 1; privset->priv_cnt = count; privset->control = 0; for (i = 0; i < count; i++) { privset->priv[i].luid.hi_part = 0; - privset->priv[i].luid.lo_part = i + SMB_PRIV_MIN; + privset->priv[i].luid.lo_part = i + SE_MIN_LUID; privset->priv[i].attrs = 0; } } @@ -280,6 +277,25 @@ smb_privset_copy(smb_privset_t *dst, smb_privset_t *src) } /* + * smb_privset_merge + * + * Enable the privileges that are enabled in src in dst + */ +void +smb_privset_merge(smb_privset_t *dst, smb_privset_t *src) +{ + int i; + + if (src == NULL || dst == NULL) + return; + + for (i = 0; i < src->priv_cnt; i++) { + if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED) + smb_privset_enable(dst, src->priv[i].luid.lo_part); + } +} + +/* * smb_privset_free * * This will free the memory allocated by the 'privset'. @@ -354,7 +370,7 @@ smb_privset_query(smb_privset_t *privset, uint32_t id) static char * smb_priv_getname(uint32_t id) { - if (id < SMB_PRIV_MIN || id > SMB_PRIV_MAX) + if (id < SE_MIN_LUID || id > SE_MAX_LUID) return ("Unknown Privilege"); return (priv_table[id].name); diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c index 10026d7418..cc0cddebcd 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_pwdutil.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -173,8 +173,7 @@ smb_pwd_update(const char *name, const char *password, int control) boolean_t user_disable = B_FALSE; char uxbuf[1024]; struct passwd uxpw; - int lm_level; - char *lm_str; + int64_t lm_level; err = smb_pwd_lock(); if (err != SMB_PWE_SUCCESS) @@ -202,13 +201,8 @@ smb_pwd_update(const char *name, const char *password, int control) goto passwd_exit; } - lm_str = smb_config_getenv(SMB_CI_LM_LEVEL); - if (lm_str) { - lm_level = strtoul(lm_str, 0, 10); - free(lm_str); - } else { + if (smb_config_getnum(SMB_CI_LM_LEVEL, &lm_level) != SMBD_SMF_OK) lm_level = 4; - } if (lm_level >= 4) control |= SMB_PWC_NOLM; diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c index 1f5083f448..4460e70154 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -60,95 +60,6 @@ smb_smf_scf_log_error(char *msg) } /* - * Check if instance with given name exists for a service. - * Returns 0 is instance exist - */ -int -smb_smf_instance_exists(smb_scfhandle_t *handle, char *inst_name) -{ - int ret = SMBD_SMF_OK; - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) != SCF_SUCCESS) - ret = SMBD_SMF_SYSTEM_ERR; - - scf_instance_destroy(handle->scf_instance); - handle->scf_instance = NULL; - return (ret); -} - -/* - * Create a service instance. returns 0 if successful. - * If instance already exists enable it. - */ -int -smb_smf_instance_create(smb_scfhandle_t *handle, char *serv_prefix, - char *inst_name) -{ - char *instance; - int ret = SMBD_SMF_OK; - int sz; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - if (!serv_prefix || !inst_name) - return (SMBD_SMF_SYSTEM_ERR); - - sz = strlen(serv_prefix) + strlen(inst_name) + 2; - instance = malloc(sz); - if (!instance) - return (SMBD_SMF_NO_MEMORY); - - (void) snprintf(instance, sz, "%s:%s", serv_prefix, inst_name); - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) != SCF_SUCCESS) { - if (scf_service_add_instance(handle->scf_service, - inst_name, handle->scf_instance) == SCF_SUCCESS) { - if (smf_enable_instance(instance, 0)) - ret = SMBD_SMF_SYSTEM_ERR; - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - if (smf_enable_instance(instance, 0)) - ret = SMBD_SMF_SYSTEM_ERR; - } - free(instance); - return (ret); -} - -/* - * Delete a specified instance. Return SMBD_SMF_OK for success. - */ -int -smb_smf_instance_delete(smb_scfhandle_t *handle, char *inst_name) -{ - int ret = SMBD_SMF_OK; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - handle->scf_instance = scf_instance_create(handle->scf_handle); - if (scf_service_get_instance(handle->scf_service, inst_name, - handle->scf_instance) == SCF_SUCCESS) { - if (scf_instance_delete(handle->scf_instance) == SCF_SUCCESS) { - return (ret); - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - smb_smf_scf_log_error(NULL); - ret = SMBD_SMF_SYSTEM_ERR; - } - return (ret); -} - -/* * smb_smf_create_service_pgroup(handle, pgroup) * * create a new property group at service level. @@ -196,152 +107,6 @@ smb_smf_create_service_pgroup(smb_scfhandle_t *handle, char *pgroup) } /* - * smb_smf_create_instance_pgroup(handle, pgroup) - * - * create a new property group at instance level. - */ -int -smb_smf_create_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) { - return (SMBD_SMF_SYSTEM_ERR); - } - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * if the pgroup exists, we are done. If it doesn't, then we - * need to actually add one to the service instance. - */ - if (scf_instance_get_pg(handle->scf_instance, - pgroup, handle->scf_pg) != 0) { - /* doesn't exist so create one */ - if (scf_instance_add_pg(handle->scf_instance, pgroup, - SCF_GROUP_FRAMEWORK, 0, handle->scf_pg) != 0) { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error(NULL); - switch (err) { - case SCF_ERROR_PERMISSION_DENIED: - ret = SMBD_SMF_NO_PERMISSION; - break; - default: - ret = SMBD_SMF_SYSTEM_ERR; - break; - } - } - } - return (ret); -} - -/* - * smb_smf_delete_service_pgroup(handle, pgroup) - * - * remove the property group from the current service. - * but only if it actually exists. - */ -int -smb_smf_delete_service_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) { - return (SMBD_SMF_SYSTEM_ERR); - } - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * only delete if it does exist. - */ - if (scf_service_get_pg(handle->scf_service, - pgroup, handle->scf_pg) == 0) { - /* does exist so delete it */ - if (scf_pg_delete(handle->scf_pg) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - err = scf_error(); - if (err != SCF_ERROR_NONE) { - smb_smf_scf_log_error("SMF delpg " - "problem: %s\n"); - } - } - } else { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error("SMF getpg problem: %s\n"); - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR && - scf_error() == SCF_ERROR_PERMISSION_DENIED) { - ret = SMBD_SMF_NO_PERMISSION; - } - return (ret); -} - -/* - * smb_smf_delete_instance_pgroup(handle, pgroup) - * - * remove the property group from the current instance. - * but only if it actually exists. - */ -int -smb_smf_delete_instance_pgroup(smb_scfhandle_t *handle, char *pgroup) -{ - int ret = SMBD_SMF_OK; - int err; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - /* - * only create a handle if it doesn't exist. It is ok to exist - * since the pg handle will be set as a side effect. - */ - if (handle->scf_pg == NULL) - handle->scf_pg = scf_pg_create(handle->scf_handle); - - /* - * only delete if it does exist. - */ - if (scf_instance_get_pg(handle->scf_instance, - pgroup, handle->scf_pg) == 0) { - /* does exist so delete it */ - if (scf_pg_delete(handle->scf_pg) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - err = scf_error(); - if (err != SCF_ERROR_NONE) { - smb_smf_scf_log_error("SMF delpg " - "problem: %s\n"); - } - } - } else { - err = scf_error(); - if (err != SCF_ERROR_NONE) - smb_smf_scf_log_error("SMF getpg problem: %s\n"); - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR && - scf_error() == SCF_ERROR_PERMISSION_DENIED) - ret = SMBD_SMF_NO_PERMISSION; - - return (ret); -} - -/* * Start transaction on current pg in handle. * The pg could be service or instance level. * Must be called after pg handle is obtained @@ -413,49 +178,6 @@ smb_smf_end_transaction(smb_scfhandle_t *handle) } /* - * Deletes property in current pg - */ -int -smb_smf_delete_property(smb_scfhandle_t *handle, char *propname) -{ - int ret = SMBD_SMF_OK; - scf_transaction_entry_t *entry = NULL; - - if (handle == NULL) - return (SMBD_SMF_SYSTEM_ERR); - - /* - * properties must be set in transactions and don't take - * effect until the transaction has been ended/committed. - */ - entry = scf_entry_create(handle->scf_handle); - if (entry != NULL) { - if (scf_transaction_property_delete(handle->scf_trans, entry, - propname) != 0) { - ret = SMBD_SMF_SYSTEM_ERR; - } - } else { - ret = SMBD_SMF_SYSTEM_ERR; - } - if (ret == SMBD_SMF_SYSTEM_ERR) { - switch (scf_error()) { - case SCF_ERROR_PERMISSION_DENIED: - ret = SMBD_SMF_NO_PERMISSION; - break; - } - } - - /* - * cleanup if there were any errors that didn't leave these - * values where they would be cleaned up later. - */ - if ((ret != SMBD_SMF_OK) && (entry != NULL)) - scf_entry_destroy(entry); - - return (ret); -} - -/* * Sets string property in current pg */ int @@ -843,103 +565,6 @@ smb_smf_get_opaque_property(smb_scfhandle_t *handle, char *propname, } /* - * Get property based on property type. Returns string value of that - * property. Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN - * supported. - */ -int -smb_smf_get_property(smb_scfhandle_t *handle, int proptype, char *propname, - char *valstr, size_t sz) -{ - int64_t valint = 0; - uint8_t valbool = 0; - int ret = SMBD_SMF_OK; - - switch (proptype) { - case SCF_TYPE_ASTRING: - ret = smb_smf_get_string_property(handle, propname, - valstr, sz); - break; - case SCF_TYPE_INTEGER: - if ((ret = smb_smf_get_integer_property(handle, propname, - &valint)) != 0) - return (ret); - (void) snprintf(valstr, sz, "%lld", valint); - break; - case SCF_TYPE_BOOLEAN: - if ((ret = smb_smf_get_boolean_property(handle, propname, - &valbool)) != 0) - return (ret); - (void) strlcpy(valstr, (valbool ? "true" : "false"), sz); - break; - default: - return (SMBD_SMF_SYSTEM_ERR); - } - return (ret); -} - -/* - * Set property based on property type. - * Only SCF_TYPE_ASTRING, SCF_TYPE_INTEGER, SCF_TYPE_BOOLEAN supported. - */ -int -smb_smf_set_property(smb_scfhandle_t *handle, int proptype, - char *propname, char *valstr) -{ - int64_t valint = 0; - uint8_t valbool = 0; - int ret = SMBD_SMF_OK; - - switch (proptype) { - case SCF_TYPE_ASTRING: - ret = smb_smf_set_string_property(handle, propname, - valstr); - break; - case SCF_TYPE_INTEGER: - valint = strtol(valstr, 0, 10); - ret = smb_smf_set_integer_property(handle, propname, - valint); - break; - case SCF_TYPE_BOOLEAN: - if (strcasecmp(valstr, "true") == 0) - valbool = 1; - ret = smb_smf_set_boolean_property(handle, propname, valbool); - break; - default: - return (SMBD_SMF_SYSTEM_ERR); - } - return (ret); -} - -/* - * Gets an instance iterator for the service specified. - */ -smb_scfhandle_t * -smb_smf_get_iterator(char *svc_name) -{ - smb_scfhandle_t *handle = NULL; - - handle = smb_smf_scf_init(svc_name); - if (!handle) - return (NULL); - - handle->scf_inst_iter = scf_iter_create(handle->scf_handle); - if (handle->scf_inst_iter) { - if (scf_iter_service_instances(handle->scf_inst_iter, - handle->scf_service) != 0) { - smb_smf_scf_fini(handle); - handle = NULL; - } else { - handle->scf_instance = NULL; - } - } else { - smb_smf_scf_fini(handle); - handle = NULL; - } - return (handle); -} - -/* * smb_smf_scf_init() * * must be called before using any of the SCF functions. diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_util.c b/usr/src/lib/smbsrv/libsmb/common/smb_util.c index bce8efee8e..b1c5c32653 100644 --- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c +++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -30,10 +30,10 @@ #include <string.h> #include <stdlib.h> #include <pthread.h> -#include <syslog.h> #include <sys/varargs.h> #include <sys/types.h> #include <smbsrv/string.h> +#include <smbsrv/libsmb.h> #define C2H(c) "0123456789ABCDEF"[(c)] #define H2C(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ @@ -56,7 +56,7 @@ * */ void -hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) +hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start) { static char *hex = "0123456789ABCDEF"; int i, count; @@ -67,13 +67,8 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) char *ap = ascbuf; char *hp = hexbuf; - if ((p = buffer) == 0) { - if (log) - syslog(LOG_DEBUG, "hexdump: (null)"); - else - (void) printf("hexdump: (null)\n"); + if ((p = buffer) == NULL) return; - } offset = *start; @@ -83,12 +78,7 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) for (i = 0; i < nbytes; ++i) { if (i && (i % 16) == 0) { - if (log) - syslog(LOG_DEBUG, - "%06X %s %s", offset, hexbuf, ascbuf); - else - (void) printf("%06X %s %s\n", - offset, hexbuf, ascbuf); + smb_tracef("%06X %s %s", offset, hexbuf, ascbuf); ap = ascbuf; hp = hexbuf; count = 0; @@ -104,13 +94,7 @@ hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start, int log) } if (count) { - if (log) - syslog(LOG_DEBUG, - "%06X %-48s %s", offset, hexbuf, ascbuf); - else - (void) printf("%06X %-48s %s\n", - offset, hexbuf, ascbuf); - + smb_tracef("%06X %-48s %s", offset, hexbuf, ascbuf); offset += count; } @@ -122,7 +106,7 @@ hexdump(unsigned char *buffer, int nbytes) { unsigned long start = 0; - hexdump_offset(buffer, nbytes, &start, 1); + hexdump_offset(buffer, nbytes, &start); } /* @@ -213,8 +197,8 @@ trim_whitespace(char *buf) char *p = buf; char *q = buf; - if (buf == 0) - return (0); + if (buf == NULL) + return (NULL); while (*p && isspace(*p)) ++p; diff --git a/usr/src/lib/smbsrv/libsmb/i386/Makefile b/usr/src/lib/smbsrv/libsmb/i386/Makefile index 710c9eb3dd..7ac7d3d534 100644 --- a/usr/src/lib/smbsrv/libsmb/i386/Makefile +++ b/usr/src/lib/smbsrv/libsmb/i386/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,7 @@ include ../Makefile.com +LDLIBS += -lsqlite DYNFLAGS += -R/usr/lib/smbsrv install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparc/Makefile b/usr/src/lib/smbsrv/libsmb/sparc/Makefile index 710c9eb3dd..7ac7d3d534 100644 --- a/usr/src/lib/smbsrv/libsmb/sparc/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparc/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,6 +27,7 @@ include ../Makefile.com +LDLIBS += -lsqlite DYNFLAGS += -R/usr/lib/smbsrv install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile index b3c4916b0c..03c6ea5b61 100644 --- a/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile +++ b/usr/src/lib/smbsrv/libsmb/sparcv9/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h index 01de8f7f02..f7034dd64d 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/libsmbns.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,6 +74,8 @@ typedef enum adjoin_status { } adjoin_status_t; /* ADS functions */ +extern void ads_init(void); +extern void ads_refresh(void); extern ADS_HANDLE *ads_open(void); extern void ads_close(ADS_HANDLE *); extern int ads_publish_share(ADS_HANDLE *, const char *, const char *, @@ -84,11 +86,12 @@ extern int ads_build_unc_name(char *, int, const char *, const char *); extern int ads_lookup_share(ADS_HANDLE *, const char *, const char *, char *); extern int ads_add_share(ADS_HANDLE *, const char *, const char *, const char *); -extern int ads_domain_change_notify_handler(char *); -extern adjoin_status_t ads_join(char *, char *, char *, int); +extern adjoin_status_t ads_join(char *, char *, char *, char *, int); extern char *adjoin_report_err(adjoin_status_t status); +extern int ads_domain_change_cleanup(char *); /* DYNDNS functions */ +extern int dns_msgid_init(void); extern int dyndns_update(void); extern int dyndns_clear_rev_zone(void); @@ -97,8 +100,8 @@ extern int smb_kinit(char *user, char *passwd); /* NETBIOS Functions */ -extern int msdcs_lookup_ads(void); -extern void smb_netbios_start(void); +extern int msdcs_lookup_ads(char *); +extern int smb_netbios_start(void); extern void smb_netbios_shutdown(void); extern void smb_netbios_name_reconfig(void); @@ -142,10 +145,7 @@ struct ip_alias { #define GATEWAY_FILE "/etc/defaultrouter" /* NIC Config functions */ -extern void smb_resolver_init(void); -extern void smb_resolver_close(void); extern int smb_get_nameservers(struct in_addr *, int); -extern uint16_t smb_get_next_resid(void); extern void smb_nic_lock(void); extern void smb_nic_unlock(void); extern int smb_nic_init(void); diff --git a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers index 63cf1a8f5b..ed0fde1e08 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbns/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -31,18 +31,20 @@ SUNWprivate { ads_add_share; ads_build_unc_name; ads_close; - ads_domain_change_notify_handler; + ads_domain_change_cleanup; + ads_init; ads_join; ads_lookup_share; ads_open; ads_publish_share; + ads_refresh; ads_remove_share; + dns_msgid_init; dyndns_clear_rev_zone; dyndns_update; msdcs_lookup_ads; smb_browser_config; smb_get_nameservers; - smb_get_next_resid; smb_kinit; smb_netbios_name_reconfig; smb_netbios_start; @@ -75,8 +77,6 @@ SUNWprivate { smb_nic_status; smb_nic_unlock; smb_nic_validate_ip_address; - smb_resolver_close; - smb_resolver_init; local: *; }; diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c index 5ea03bbd41..b988026dd3 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,10 +59,14 @@ #define ADS_COMPUTERS_CN "Computers" #define ADS_COMPUTER_NUM_ATTR 7 #define ADS_SHARE_NUM_ATTR 3 +#define ADS_SITE_MAX MAXHOSTNAMELEN /* current ADS server to communicate with */ ADS_HOST_INFO *ads_host_info = NULL; -mutex_t ads_mtx; +mutex_t ads_host_mtx; +char ads_site[ADS_SITE_MAX]; +mutex_t ads_site_mtx; + /* * adjoin_errmsg @@ -88,7 +92,7 @@ static char *adjoin_errmsg[] = { "ADJOIN failed to refresh SMB service." }; -static ADS_HANDLE *ads_open_main(char *user, char *password); +static ADS_HANDLE *ads_open_main(char *domain, char *user, char *password); static int ads_bind(ADS_HANDLE *); static void ads_get_computer_dn(ADS_HANDLE *, char *, size_t); static char *ads_get_host_principal(char *fqhost); @@ -105,6 +109,39 @@ static krb5_kvno ads_lookup_computer_attr_kvno(ADS_HANDLE *ah); static int ads_gen_machine_passwd(char *machine_passwd, int bufsz); static ADS_HOST_INFO *ads_get_host_info(void); static void ads_set_host_info(ADS_HOST_INFO *host); +static void ads_free_host_info(void); + +/* + * ads_init + * + * Initializes the ads_site global variable. + */ +void +ads_init(void) +{ + (void) mutex_lock(&ads_site_mtx); + (void) smb_config_getstr(SMB_CI_ADS_SITE, ads_site, sizeof (ads_site)); + (void) mutex_unlock(&ads_site_mtx); +} + +/* + * ads_refresh + * + * If the ads_site has changed, clear the ads_host_info cache. + */ +void +ads_refresh(void) +{ + char new_site[ADS_SITE_MAX]; + + (void) smb_config_getstr(SMB_CI_ADS_SITE, new_site, sizeof (new_site)); + (void) mutex_lock(&ads_site_mtx); + if (strcasecmp(ads_site, new_site)) { + (void) strlcpy(ads_site, new_site, sizeof (ads_site)); + ads_free_host_info(); + } + (void) mutex_unlock(&ads_site_mtx); +} /* * ads_build_unc_name @@ -118,9 +155,9 @@ int ads_build_unc_name(char *unc_name, int maxlen, const char *hostname, const char *shareUNC) { - char my_domain[ADS_MAXBUFLEN]; + char my_domain[MAXHOSTNAMELEN]; - if (smb_getdomainname(my_domain, sizeof (my_domain)) != 0) + if (smb_getfqdomainname(my_domain, sizeof (my_domain)) != 0) return (-1); (void) snprintf(unc_name, maxlen, "\\\\%s.%s\\%s", @@ -301,10 +338,10 @@ ads_free_host_list(ADS_HOST_INFO *host_list, int count) static void ads_set_host_info(ADS_HOST_INFO *host) { - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); if (!ads_host_info) ads_host_info = host; - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); } /* @@ -316,9 +353,9 @@ ads_get_host_info(void) { ADS_HOST_INFO *host; - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); host = ads_host_info; - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); return (host); } /* @@ -355,14 +392,13 @@ ads_find_host(char *ns, char *domain, int *port, char *service, int *go_next) int s; uint16_t id, rid, data_len, eport; int ipaddr; - struct hostent *h; char buf[NS_PACKETSZ], buf2[NS_PACKETSZ]; char *bufptr, *str; int i, ret; int queryReq; uint16_t query_cnt, ans_cnt, namser_cnt, addit_cnt; int quest_type, quest_class; - int dns_ip, decode_ip; + int dns_ip; struct in_addr addr; uint16_t flags = 0; int force_recurs = 0; @@ -397,7 +433,7 @@ retry: (void) memset(buf, 0, NS_PACKETSZ); bufptr = buf; - id = smb_get_next_resid(); + id = dns_get_msgid(); if (dyndns_build_header(&bufptr, BUFLEN_UDP(bufptr, buf), id, queryReq, query_cnt, ans_cnt, namser_cnt, addit_cnt, flags) == -1) { (void) close(s); @@ -514,13 +550,7 @@ retry: } /* check additional section to get IP address of ads host */ - decode_ip = 1; - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_ADS_IPLOOKUP) == 1) - decode_ip = 0; - smb_config_unlock(); - - if (decode_ip && (addit_cnt > 0)) { + if (addit_cnt > 0) { int j; ads_hosts_list2 = (ADS_HOST_INFO *) @@ -589,50 +619,8 @@ retry: return (ads_host); } ads_free_host_list(ads_hosts_list2, addit_cnt); - } else { - /* use DNS to get IP address of ads host */ - /* - * Shouldn't get here unless entries exist in - * DNS but DNS server did - * not put them in additional section of DNS reply packet. - */ - for (i = 0; i < ans_cnt; i++) { - h = gethostbyname(ads_hosts_list[i].name); - if (h == NULL) - continue; - if (h->h_addr == NULL) - continue; - (void) memcpy(&ads_hosts_list[i].ip_addr, - h->h_addr, sizeof (addr.s_addr)); - if (ads_ping(ads_hosts_list[i].ip_addr) == 0) { - ads_host = (ADS_HOST_INFO *) - malloc(sizeof (ADS_HOST_INFO)); - if (ads_host == NULL) { - ads_free_host_list(ads_hosts_list, - ans_cnt); - return (NULL); - } - bzero(ads_host, sizeof (ADS_HOST_INFO)); - ads_host->name = strdup(ads_hosts_list[i].name); - if (ads_host->name == NULL) { - ads_free_host_list(ads_hosts_list, - ans_cnt); - return (NULL); - } - ads_host->ip_addr = ads_hosts_list[i].ip_addr; - ads_host->port = ads_hosts_list[i].port; - *port = ads_host->port; - addr.s_addr = ads_host->ip_addr; - syslog(LOG_DEBUG, "smb_ads: Found ADS server" - " using DNS: %s (%s) port %d", - ads_host->name, inet_ntoa(addr), - ads_host->port); - ads_free_host_list(ads_hosts_list, ans_cnt); - ads_set_host_info(ads_host); - return (ads_host); - } - } } + syslog(LOG_ERR, "smb_ads: Can't get IP for " "ADS host or ADS host is down.\n"); ads_free_host_list(ads_hosts_list, ans_cnt); @@ -720,16 +708,16 @@ ads_convert_domain(char *s) * ads_free_host_info * Free the memory use by the global ads_host_info and set it to NULL. */ -void +static void ads_free_host_info(void) { - (void) mutex_lock(&ads_mtx); + (void) mutex_lock(&ads_host_mtx); if (ads_host_info) { free(ads_host_info->name); free(ads_host_info); ads_host_info = NULL; } - (void) mutex_unlock(&ads_mtx); + (void) mutex_unlock(&ads_host_mtx); } /* @@ -743,12 +731,15 @@ ads_free_host_info(void) ADS_HANDLE * ads_open(void) { - uint32_t mode = smb_get_security_mode(); + char domain[MAXHOSTNAMELEN]; - if (mode != SMB_SECMODE_DOMAIN) + if (smb_config_get_secmode() != SMB_SECMODE_DOMAIN) return (NULL); - return (ads_open_main(NULL, NULL)); + if (smb_getfqdomainname(domain, MAXHOSTNAMELEN) != 0) + return (NULL); + + return (ads_open_main(domain, NULL, NULL)); } /* @@ -770,75 +761,54 @@ ads_open(void) * * The ads_bind() routine is also called before the ADS handle is returned. * Parameters: - * None + * domain - fully-qualified domain name + * user - the user account for whom the Kerberos TGT ticket and ADS + * service tickets are acquired. + * password - password of the specified user + * * Returns: * NULL : can't connect to ADS server or other errors * ADS_HANDLE* : handle to ADS server */ -ADS_HANDLE * -ads_open_main(char *user, char *password) +static ADS_HANDLE * +ads_open_main(char *domain, char *user, char *password) { ADS_HANDLE *ah; LDAP *ld; int version = 3, ads_port, find_ads_retry; - char domain[MAXHOSTNAMELEN]; - int enable; ADS_HOST_INFO *ads_host = NULL; struct in_addr addr; - char *site, *service = NULL, *site_service = NULL; - int service_sz; + char site[ADS_SITE_MAX]; + char service[MAXHOSTNAMELEN]; + char site_service[MAXHOSTNAMELEN]; struct in_addr ns_list[MAXNS]; int i, cnt, go_next; - if (smb_getdomainname(domain, MAXHOSTNAMELEN) != 0) - return (NULL); - - smb_config_rdlock(); - enable = smb_config_getyorn(SMB_CI_ADS_ENABLE); - if (!enable) { - smb_config_unlock(); - return (NULL); - } - site = smb_config_getstr(SMB_CI_ADS_SITE); - smb_config_unlock(); + (void) mutex_lock(&ads_site_mtx); + (void) strlcpy(site, ads_site, sizeof (site)); + (void) mutex_unlock(&ads_site_mtx); find_ads_retry = 0; find_ads_host: ads_host = ads_get_host_info(); if (!ads_host) { - if (site && *site != 0) { - service_sz = strlen("_ldap._tcp.._sites.dc._msdcs.") + - strlen(site) + strlen(domain) + 1; - site_service = (char *)malloc(service_sz); - if (site_service == NULL) { - syslog(LOG_ERR, "smb_ads: No ADS host found" - " malloc failed..."); - return (NULL); - } - (void) snprintf(site_service, service_sz, + if (*site != '\0') { + (void) snprintf(site_service, sizeof (site_service), "_ldap._tcp.%s._sites.dc._msdcs.%s", site, domain); + } else { + *site_service = '\0'; } - service_sz = strlen("_ldap._tcp.dc._msdcs.") + strlen(domain) - + 1; - service = (char *)malloc(service_sz); - if (service == NULL) { - syslog(LOG_ERR, "smb_ads: No ADS host found malloc" - " failed..."); - if (site_service != NULL) - (void) free(site_service); - return (NULL); - } - (void) snprintf(service, service_sz, "_ldap._tcp.dc._msdcs.%s", - domain); + (void) snprintf(service, sizeof (service), + "_ldap._tcp.dc._msdcs.%s", domain); cnt = smb_get_nameservers(ns_list, MAXNS); ads_host = NULL; go_next = 0; for (i = 0; i < cnt; i++) { - if (site_service != NULL) { + if (*site_service != '\0') { ads_host = ads_find_host(inet_ntoa(ns_list[i]), domain, &ads_port, site_service, &go_next); } @@ -853,11 +823,6 @@ find_ads_host: } } - if (site_service) - (void) free(site_service); - if (service) - (void) free(service); - if (ads_host == NULL) { syslog(LOG_ERR, "smb_ads: No ADS host found from " "configured nameservers"); @@ -1789,8 +1754,11 @@ ads_get_host_principals(char *fqhost, char *domain, char **princ, if (fqhost) { (void) strlcpy(hostname, fqhost, MAXHOSTNAMELEN); } else { - if (smb_getfqhostname(hostname, MAXHOSTNAMELEN) != 0) + if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) return (-1); + + (void) snprintf(hostname, MAXHOSTNAMELEN, "%s.%s", hostname, + domain); } if ((p = ads_get_host_principal(hostname)) == NULL) { @@ -1846,13 +1814,13 @@ ads_computer_op(ADS_HANDLE *ah, int op) char usrctl_buf[16]; int max; - if (smb_getfqhostname(fqhost, MAXHOSTNAMELEN) != 0) - return (-1); - - if (smb_gethostname(sam_acct, MAXHOSTNAMELEN, 0) != 0) + if (smb_gethostname(fqhost, MAXHOSTNAMELEN, 0) != 0) return (-1); + (void) strlcpy(sam_acct, fqhost, MAXHOSTNAMELEN + 1); (void) strlcat(sam_acct, "$", MAXHOSTNAMELEN + 1); + (void) snprintf(fqhost, MAXHOSTNAMELEN, "%s.%s", fqhost, + ah->domain); if (ads_get_host_principals(fqhost, ah->domain, &svc_principal, &user_principal) == -1) { @@ -2165,22 +2133,32 @@ ads_gen_machine_passwd(char *machine_passwd, int bufsz) } /* - * ads_domain_change_notify_handler + * ads_domain_change_cleanup * - * Clear the host info cache and remove the old keys from the keytab - * as the ads_domain property has changed. + * If we're attempting to join the system to a new domain, the keys for + * the host principal regarding the old domain should be removed from + * Kerberos keytab. Also, the ads_host_info cache should be cleared. * - * domain - is the old ADS domain name. + * newdom is fully-qualified domain name. It can be set to empty string + * if user attempts to switch to workgroup mode. */ int -ads_domain_change_notify_handler(char *domain) +ads_domain_change_cleanup(char *newdom) { + char origdom[MAXHOSTNAMELEN]; char *princ_r; krb5_context ctx = NULL; krb5_principal krb5princ; int rc; - if (ads_get_host_principals(NULL, domain, NULL, &princ_r) == -1) + if (smb_getfqdomainname(origdom, MAXHOSTNAMELEN)) + return (0); + + if (strcasecmp(origdom, newdom) == 0) + return (0); + + ads_free_host_info(); + if (ads_get_host_principals(NULL, origdom, NULL, &princ_r) == -1) return (-1); if (smb_krb5_ctx_init(&ctx) != 0) { @@ -2198,7 +2176,7 @@ ads_domain_change_notify_handler(char *domain) rc = smb_krb5_remove_keytab_entries(ctx, krb5princ, SMBNS_KRB5_KEYTAB); free(princ_r); smb_krb5_ctx_fini(ctx); - ads_free_host_info(); + return (rc); } @@ -2228,7 +2206,8 @@ ads_domain_change_notify_handler(char *domain) * principal after the domain join operation. */ adjoin_status_t -ads_join(char *user, char *usr_passwd, char *machine_passwd, int len) +ads_join(char *domain, char *user, char *usr_passwd, char *machine_passwd, + int len) { ADS_HANDLE *ah = NULL; krb5_context ctx = NULL; @@ -2250,7 +2229,7 @@ ads_join(char *user, char *usr_passwd, char *machine_passwd, int len) krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_ARCFOUR_HMAC, ENCTYPE_AES128_CTS_HMAC_SHA1_96}; - if ((ah = ads_open_main(user, usr_passwd)) == NULL) { + if ((ah = ads_open_main(domain, user, usr_passwd)) == NULL) { (void) smb_config_refresh(); return (ADJOIN_ERR_GET_HANDLE); } diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c index 853d1ff814..7ab634fd4d 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_browser.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,6 +37,7 @@ #include <sys/socket.h> #include <arpa/inet.h> +#include <smbsrv/libsmb.h> #include <smbsrv/libsmbns.h> #include <smbsrv/cifs.h> @@ -852,13 +853,9 @@ smb_browser_send_HostAnnouncement(int net, int32_t next_announcement, uint32_t type; char resource_domain[SMB_PI_MAX_DOMAIN]; - syslog(LOG_DEBUG, "smb_browse: send_HostAnnouncement(%d)", net); - - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; (void) utf8_strupr(resource_domain); - smb_config_unlock(); if (addr == 0) { /* Local master Browser */ @@ -1134,15 +1131,10 @@ smb_browser_config(void) int net; char resource_domain[SMB_PI_MAX_DOMAIN]; - syslog(LOG_DEBUG, "smb_browse: reconfigure"); - smb_browser_init(); - - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; (void) utf8_strupr(resource_domain); - smb_config_unlock(); /* domain<00> */ smb_init_name_struct((unsigned char *)resource_domain, 0x00, @@ -1201,11 +1193,7 @@ smb_browser_init() net_cfg_t cfg; (void) smb_gethostname(hostname, MAXHOSTNAMELEN, 1); - - smb_config_rdlock(); - (void) strlcpy(cmnt, smb_config_getstr(SMB_CI_SYS_CMNT), - sizeof (cmnt)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_SYS_CMNT, cmnt, sizeof (cmnt)); smb_nc_cnt = smb_nic_get_num(); for (i = 0; i < smb_nc_cnt; i++) { @@ -1281,12 +1269,10 @@ smb_browser_non_master_duties(int net) smb_browser_putnet(subnet); smb_browser_send_HostAnnouncement(net, interval, 0, 0x1D); + if (smb_getdomainname(resource_domain, SMB_PI_MAX_DOMAIN) != 0) + return; - smb_config_rdlock(); - (void) strlcpy(resource_domain, - smb_config_getstr(SMB_CI_DOMAIN_NAME), SMB_PI_MAX_DOMAIN); (void) utf8_strupr(resource_domain); - smb_config_unlock(); smb_init_name_struct((unsigned char *)resource_domain, 0x1D, 0, 0, 0, 0, 0, &name); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c index 094c1b4946..c0f870b2ad 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,16 +52,39 @@ #define DEL_NONE 2 /* Maximum retires if not authoritative */ #define MAX_AUTH_RETRIES 3 +/* Number of times to retry a DNS query */ +#define DYNDNS_MAX_QUERY_RETRIES 3 +/* Timeout value, in seconds, for DNS query responses */ +#define DYNDNS_QUERY_TIMEOUT 2 -static int -dyndns_enabled(void) +static uint16_t dns_msgid; +mutex_t dns_msgid_mtx; + +int +dns_msgid_init(void) { - int enabled; + struct __res_state res; + + bzero(&res, sizeof (struct __res_state)); + if (res_ninit(&res) < 0) + return (-1); - smb_config_rdlock(); - enabled = smb_config_getyorn(SMB_CI_DYNDNS_ENABLE); - smb_config_unlock(); - return (enabled); + (void) mutex_lock(&dns_msgid_mtx); + dns_msgid = res.id; + (void) mutex_unlock(&dns_msgid_mtx); + res_nclose(&res); + return (0); +} + +int +dns_get_msgid(void) +{ + uint16_t id; + + (void) mutex_lock(&dns_msgid_mtx); + id = ++dns_msgid; + (void) mutex_unlock(&dns_msgid_mtx); + return (id); } /* @@ -651,7 +674,7 @@ dyndns_build_tkey_msg(char *buf, char *key_name, uint16_t *id, (void) memset(buf, 0, MAX_TCP_SIZE); bufptr = buf; - *id = smb_get_next_resid(); + *id = dns_get_msgid(); /* add TCP length info that follows this field */ bufptr = dyndns_put_nshort(bufptr, @@ -931,7 +954,7 @@ dyndns_build_add_remove_msg(char *buf, int update_zone, const char *hostname, bufptr = buf; if (*id == 0) - *id = smb_get_next_resid(); + *id = dns_get_msgid(); if (dyndns_build_header(&bufptr, BUFLEN_UDP(bufptr, buf), *id, queryReq, zoneCount, preqCount, updateCount, additionalCount, 0) == -1) { @@ -1114,13 +1137,7 @@ dyndns_build_signed_tsig_msg(char *buf, int update_zone, const char *hostname, /* * dyndns_udp_send_recv - * This routine sends and receives UDP DNS request and reply messages. Time - * out value and retry count is indicated by two environment variables: - * lookup_dns_retry_cnt - * lookup_dns_retry_sec - * If either of these two variables are undefined or their value exceed the - * value of 10 then a default value of 3 retry and/or a default value of 3 - * secs are used. + * This routine sends and receives UDP DNS request and reply messages. * * Pre-condition: Caller must call dyndns_open_init_socket() before calling * this function. @@ -1137,34 +1154,15 @@ dyndns_build_signed_tsig_msg(char *buf, int update_zone, const char *hostname, int dyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf) { - int i, retval, addr_len, max_retries; + int i, retval, addr_len; struct timeval tv, timeout; fd_set rfds; struct sockaddr_in from_addr; - char *p; - - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_DYNDNS_RETRY_COUNT); - if (p == NULL || *p == 0) { - max_retries = 3; - } else { - max_retries = atoi(p); - if (max_retries < 1 || max_retries > 10) - max_retries = 3; - } - p = smb_config_getstr(SMB_CI_DYNDNS_RETRY_SEC); timeout.tv_usec = 0; - if (p == NULL || *p == 0) { - timeout.tv_sec = 3; - } else { - timeout.tv_sec = atoi(p); - if (timeout.tv_sec < 1 || timeout.tv_sec > 10) - timeout.tv_sec = 3; - } - smb_config_unlock(); + timeout.tv_sec = DYNDNS_QUERY_TIMEOUT; - for (i = 0; i < max_retries + 1; i++) { + for (i = 0; i <= DYNDNS_MAX_QUERY_RETRIES; i++) { if (send(s, buf, buf_sz, 0) == -1) { syslog(LOG_ERR, "dyndns: UDP send error (%s)\n", strerror(errno)); @@ -1193,7 +1191,8 @@ dyndns_udp_send_recv(int s, char *buf, int buf_sz, char *rec_buf) } } - if (i == (max_retries + 1)) { /* did not receive anything */ + /* did not receive anything */ + if (i == (DYNDNS_MAX_QUERY_RETRIES + 1)) { syslog(LOG_ERR, "dyndns: max retries for UDP recv reached\n"); return (-1); } @@ -1506,7 +1505,7 @@ retry_higher: return (-1); } - if (smb_get_security_mode() == SMB_SECMODE_DOMAIN) + if (smb_config_get_secmode() == SMB_SECMODE_DOMAIN) ret = dyndns_sec_add_remove_entry(update_zone, hostname, ip_addr, life_time, update_type, del_type, dns_str); @@ -1679,7 +1678,7 @@ dyndns_update(void) struct in_addr addr; int rc; - if (!dyndns_enabled()) + if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) return (-1); if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) @@ -1760,7 +1759,7 @@ dyndns_clear_rev_zone(void) struct in_addr addr; int rc; - if (!dyndns_enabled()) + if (!smb_config_getbool(SMB_CI_DYNDNS_ENABLE)) return (-1); if (smb_getfqhostname(fqdn, MAXHOSTNAMELEN) != 0) diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h index 7140eb4d59..42f69751cc 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_dyndns.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -182,6 +182,7 @@ extern "C" { #define BUFLEN_TCP(x, y) (MAX_TCP_SIZE-(x-y)) #define BUFLEN_UDP(x, y) (NS_PACKETSZ-(x-y)) +extern int dns_get_msgid(void); extern char *dyndns_get_nshort(char *, uint16_t *); extern char *dyndns_get_int(char *, int *); extern int dyndns_build_header(char **, int, uint16_t, int, diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c index 7b165e3b44..4f8340dcca 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -73,8 +73,8 @@ smb_netbios_shutdown(void) nb_status.state = NETBIOS_SHUT_DOWN; } -void -smb_netbios_start() +int +smb_netbios_start(void) { int rc; mutex_t *mp; @@ -84,13 +84,12 @@ smb_netbios_start() rc = pthread_create(&smb_nbns_thr, 0, smb_netbios_name_service_daemon, 0); if (rc) - return; + return (-1); mp = &nb_status.mtx; cvp = &nb_status.cv; (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_NAME_SVC_RUNNING | NETBIOS_NAME_SVC_FAILED))) { (void) cond_wait(cvp, mp); @@ -98,71 +97,62 @@ smb_netbios_start() if (nb_status.state & NETBIOS_NAME_SVC_FAILED) { (void) mutex_unlock(mp); - (void) fprintf(stderr, - "smbd: Netbios Name service startup failed!"); smb_netbios_shutdown(); - return; + return (-1); } (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Name service started."); smb_netbios_name_config(); /* Startup Netbios datagram service; port 138 */ rc = pthread_create(&smb_nbds_thr, 0, smb_netbios_datagram_service_daemon, 0); - if (rc == 0) { - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | - NETBIOS_DATAGRAM_SVC_FAILED))) { - (void) cond_wait(cvp, mp); - } + if (rc != 0) { + smb_netbios_shutdown(); + return (-1); + } - if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { - (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Datagram service " - "startup failed!"); - smb_netbios_shutdown(); - return; - } + (void) mutex_lock(mp); + while (!(nb_status.state & (NETBIOS_DATAGRAM_SVC_RUNNING | + NETBIOS_DATAGRAM_SVC_FAILED))) { + (void) cond_wait(cvp, mp); + } + + if (nb_status.state & NETBIOS_DATAGRAM_SVC_FAILED) { (void) mutex_unlock(mp); - } else { smb_netbios_shutdown(); - return; + return (-1); } - - (void) fprintf(stderr, "smbd: Netbios Datagram service started."); + (void) mutex_unlock(mp); /* Startup Netbios browser service */ rc = pthread_create(&smb_nbbs_thr, 0, smb_browser_daemon, 0); if (rc) { smb_netbios_shutdown(); - return; + return (-1); } - (void) fprintf(stderr, "smbd: Netbios Browser client started."); - /* Startup Our internal, 1 second resolution, timer */ rc = pthread_create(&smb_nbts_thr, 0, smb_netbios_timer, 0); - if (rc == 0) { - (void) mutex_lock(mp); - while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | - NETBIOS_TIMER_FAILED))) { - (void) cond_wait(cvp, mp); - } + if (rc != 0) { + smb_netbios_shutdown(); + return (-1); + } - if (nb_status.state & NETBIOS_TIMER_FAILED) { - (void) mutex_unlock(mp); - smb_netbios_shutdown(); - return; - } + (void) mutex_lock(mp); + while (!(nb_status.state & (NETBIOS_TIMER_RUNNING | + NETBIOS_TIMER_FAILED))) { + (void) cond_wait(cvp, mp); + } + + if (nb_status.state & NETBIOS_TIMER_FAILED) { (void) mutex_unlock(mp); - } else { smb_netbios_shutdown(); - return; + return (-1); } + (void) mutex_unlock(mp); - (void) fprintf(stderr, "smbd: Netbios Timer service started."); + return (0); } /*ARGSUSED*/ @@ -253,10 +243,8 @@ smb_encode_netbios_name(unsigned char *name, char suffix, unsigned char *scope, dest->name[NETBIOS_NAME_SZ - 1] = suffix; if (scope == NULL) { - smb_config_rdlock(); - (void) strlcpy((char *)dest->scope, - smb_config_getstr(SMB_CI_NBSCOPE), NETBIOS_DOMAIN_NAME_MAX); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)dest->scope, + NETBIOS_DOMAIN_NAME_MAX); } else { (void) strlcpy((char *)dest->scope, (const char *)scope, NETBIOS_DOMAIN_NAME_MAX); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c index 1e47658700..a1c3bb2c03 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_cache.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -111,11 +111,9 @@ smb_netbios_cache_lookup(struct name_entry *name) if (NETBIOS_NAME_IS_STAR(name->name)) { /* Return our address */ - smb_config_rdlock(); - (void) strlcpy((char *)scope, - smb_config_getstr(SMB_CI_NBSCOPE), sizeof (scope)); + (void) smb_config_getstr(SMB_CI_NBSCOPE, (char *)scope, + sizeof (scope)); (void) utf8_strupr((char *)scope); - smb_config_unlock(); if (smb_getnetbiosname((char *)hostname, MAXHOSTNAMELEN) != 0) return (NULL); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c index b8de94a504..f7794479ab 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netbios_name.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -2126,7 +2126,8 @@ static int smb_send_node_status_response(struct addr_entry *addr, struct name_packet *original_packet) { - uint32_t net_ipaddr, max_connections; + uint32_t net_ipaddr; + int64_t max_connections; struct arpreq arpreq; struct name_packet packet; struct resource_record answer; @@ -2166,9 +2167,8 @@ smb_send_node_status_response(struct addr_entry *addr, else net_ipaddr = cfg.ip; - smb_config_rdlock(); - max_connections = smb_config_getnum(SMB_CI_MAX_CONNECTIONS); - smb_config_unlock(); + (void) smb_config_getnum(SMB_CI_MAX_CONNECTIONS, &max_connections); + while (!scan_done) { if ((scan + 6) >= scan_end) { packet.info |= NAME_NM_FLAGS_TC; @@ -4489,10 +4489,6 @@ smb_netbios_wins_config(char *ip) { uint32_t ipaddr; - /* Return if ip == NULL since this is the same as "" */ - if (ip == NULL) - return; - ipaddr = inet_addr(ip); if (ipaddr != INADDR_NONE) { smb_nbns[nbns_num].flags = ADDR_FLAG_VALID; @@ -4511,9 +4507,10 @@ smb_netbios_name_config(void) uint32_t ipaddr; struct name_entry name; char myname[MAXHOSTNAMELEN]; - int i; + int i; int smb_nc_cnt; net_cfg_t cfg; + char wins_ip[16]; if (smb_getnetbiosname(myname, MAXHOSTNAMELEN) != 0) return; @@ -4544,10 +4541,10 @@ smb_netbios_name_config(void) bzero(smb_nbns, sizeof (addr_entry_t) * SMB_PI_MAX_WINS); /* add any configured WINS */ - smb_config_rdlock(); - smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV1)); - smb_netbios_wins_config(smb_config_getstr(SMB_CI_WINS_SRV2)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_WINS_SRV1, wins_ip, sizeof (wins_ip)); + smb_netbios_wins_config(wins_ip); + (void) smb_config_getstr(SMB_CI_WINS_SRV2, wins_ip, sizeof (wins_ip)); + smb_netbios_wins_config(wins_ip); for (i = 0; i < smb_nc_cnt; i++) { if (smb_nic_get_byind(i, &cfg) == NULL) { diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c index d74bcb168d..2631bd0f68 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_netlogon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -478,27 +478,22 @@ smb_netlogon_rdc_rsp(char *src_name, uint32_t src_ipaddr) uint32_t prefer_ipaddr = 0; char ipstr[16]; char srcip[16]; - char *p; int rc; (void) inet_ntop(AF_INET, (const void *)(&src_ipaddr), srcip, sizeof (srcip)); - smb_config_rdlock(); - if ((p = smb_config_get(SMB_CI_DOMAIN_SRV)) != 0) { - rc = inet_pton(AF_INET, p, &prefer_ipaddr); + rc = smb_config_getstr(SMB_CI_DOMAIN_SRV, ipstr, sizeof (ipstr)); + if (rc == SMBD_SMF_OK) { + rc = inet_pton(AF_INET, ipstr, &prefer_ipaddr); if (rc == 0) prefer_ipaddr = 0; if (!initialized) { - (void) inet_ntop(AF_INET, - (const void *)(&prefer_ipaddr), - ipstr, sizeof (ipstr)); syslog(LOG_DEBUG, "SMB DC Preference: %s", ipstr); initialized = 1; } } - smb_config_unlock(); syslog(LOG_DEBUG, "DC Offer [%s]: %s [%s]", resource_domain, src_name, srcip); @@ -553,49 +548,35 @@ better_dc(uint32_t cur_ip, uint32_t new_ip) * best way. The IP address isn't set up in the ADS_HANDLE so we need to * make the ads_find_host call. This will only succeed if ADS is enabled. * + * Parameter: + * nbt_domain - NETBIOS name of the domain + * * Returns 1 if a domain controller was found and its name and IP address * have been updated. Otherwise returns 0. */ int -msdcs_lookup_ads(void) +msdcs_lookup_ads(char *nbt_domain) { ADS_HOST_INFO *hinfo = 0; int ads_port = 0; char ads_domain[MAXHOSTNAMELEN]; char site_service[MAXHOSTNAMELEN]; char service[MAXHOSTNAMELEN]; - char *site; + char site[MAXHOSTNAMELEN]; char *p; char *ip_addr; struct in_addr ns_list[MAXNS]; int i, cnt, go_next; - if (smb_getdomainname(ads_domain, MAXHOSTNAMELEN) != 0) + if (!nbt_domain) return (0); - /* - * Initialize the NT domain name. - */ - (void) strlcpy(resource_domain, ads_domain, SMB_PI_MAX_DOMAIN); - if ((p = strchr(resource_domain, '.')) != 0) - *p = '\0'; - - smb_config_rdlock(); - if (smb_config_getyorn(SMB_CI_MSDCS_DISABLE) != 0) { - /* - * The system administrator doesn't - * want to use ADS to find the PDC. - */ - syslog(LOG_DEBUG, "msdcsLookupADS: disabled"); - smb_config_unlock(); + (void) strlcpy(resource_domain, nbt_domain, SMB_PI_MAX_DOMAIN); + if (smb_resolve_fqdn(nbt_domain, ads_domain, MAXHOSTNAMELEN) != 1) return (0); - } - site = smb_config_getstr(SMB_CI_ADS_SITE); - smb_config_unlock(); - syslog(LOG_DEBUG, "msdcsLookupADS %s, MAXHOSTNAMELEN=%d", - ads_domain, MAXHOSTNAMELEN); - if (site && *site != 0) { + (void) smb_config_getstr(SMB_CI_ADS_SITE, site, sizeof (site)); + if (*site != '\0') { (void) snprintf(site_service, MAXHOSTNAMELEN, "_ldap._tcp.%s._sites.dc._msdcs.%s", site, ads_domain); diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c index 6adeca1d50..2316bd595f 100644 --- a/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c +++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_nicconfig.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -57,41 +57,22 @@ static void smb_nic_clear_if_list(struct if_list *); /* This is the list we will monitor */ static net_cfg_list_t smb_nic_list = { NULL, 0 }; static pthread_mutex_t smb_nic_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t smb_ns_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* Nameserver information */ -static struct __res_state smb_res; - -void -smb_resolver_init(void) -{ - int ret; - (void) pthread_mutex_lock(&smb_ns_mutex); - ret = res_ninit(&smb_res); - (void) pthread_mutex_unlock(&smb_ns_mutex); - if (ret < 0) { - syslog(LOG_ERR, "Failed to initialize resolver lib"); - } -} - -void -smb_resolver_close(void) -{ - (void) pthread_mutex_lock(&smb_ns_mutex); - res_nclose(&smb_res); - (void) pthread_mutex_unlock(&smb_ns_mutex); -} int smb_get_nameservers(struct in_addr *ips, int sz) { union res_sockaddr_union set[MAXNS]; int i, cnt; + struct __res_state res_state; if (ips == NULL) return (0); - (void) pthread_mutex_lock(&smb_ns_mutex); - cnt = res_getservers(&smb_res, set, MAXNS); + + bzero(&res_state, sizeof (struct __res_state)); + if (res_ninit(&res_state) < 0) + return (0); + + cnt = res_getservers(&res_state, set, MAXNS); for (i = 0; i < cnt; i++) { if (i >= sz) break; @@ -100,20 +81,10 @@ smb_get_nameservers(struct in_addr *ips, int sz) inet_ntoa(ips[i])); } syslog(LOG_DEBUG, "NS Found %d name servers\n", i); - (void) pthread_mutex_unlock(&smb_ns_mutex); + res_nclose(&res_state); return (i); } -uint16_t -smb_get_next_resid(void) -{ - uint16_t id; - (void) pthread_mutex_lock(&smb_ns_mutex); - id = ++smb_res.id; - (void) pthread_mutex_unlock(&smb_ns_mutex); - return (id); -} - /* * The common NIC library will provide functions to obtain information * on all interfaces. Information will include IP addresses, netmasks @@ -651,7 +622,6 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) char excludestr[MAX_EXCLUDE_LIST_LEN]; ipaddr_t exclude[SMB_PI_MAX_NETWORKS]; int nexclude; - char *winsexclude; *number = 0; numnics = smb_nic_build_if_name(&names); @@ -662,12 +632,8 @@ smb_nic_build_network_structures(net_cfg_t **nc, int *number) } bzero(nc_array, sizeof (net_cfg_t) * numnics); - smb_config_rdlock(); - excludestr[0] = '\0'; - winsexclude = smb_config_getstr(SMB_CI_WINS_EXCL); - if (winsexclude != NULL) - (void) strlcpy(excludestr, winsexclude, sizeof (excludestr)); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_WINS_EXCL, excludestr, + sizeof (excludestr)); nexclude = smb_wins_iplist(excludestr, exclude, SMB_PI_MAX_NETWORKS); for (i = 0; i < numnics; i++) { diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h index 8d537650ac..3c450da186 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/libsmbrdr.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,7 +52,7 @@ extern unsigned char *smbrdr_ipc_get_passwd(void); /* Redirector LOGON function */ extern int mlsvc_logon(char *, char *, char *); -extern int smbrdr_rpc_readx(int, char *, int); +extern int smbrdr_readx(int, char *, int); /* Redirector rpcpipe functions */ @@ -62,14 +62,12 @@ extern int mlsvc_close_pipe(int); /* Redirector session functions */ extern void smbrdr_init(void); -extern int mlsvc_locate_domain_controller(char *); extern int mlsvc_session_native_values(int, int *, int *, int *); -extern void mlsvc_check_sessions(void); extern int mlsvc_echo(char *); extern void mlsvc_disconnect(char *); -extern int smbrdr_rpc_transact(int, char *, int, char *, int); +extern int smbrdr_transact(int, char *, int, char *, int); /* DEBUG functions */ diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers index b6902203ef..ffa2d56871 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmbrdr/common/mapfile-vers @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -27,12 +27,9 @@ SUNWprivate { global: - mlsvc_check_sessions; mlsvc_close_pipe; mlsvc_disconnect; mlsvc_echo; - mlsvc_install_pdc_cb; - mlsvc_locate_domain_controller; mlsvc_logon; mlsvc_open_pipe; mlsvc_session_native_values; @@ -47,8 +44,8 @@ SUNWprivate { smbrdr_ipc_set; smbrdr_ipc_skip_lsa_query; smbrdr_ipc_get_passwd; - smbrdr_rpc_readx; - smbrdr_rpc_transact; + smbrdr_readx; + smbrdr_transact; local: *; }; diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h index 35db51adc6..5275708b72 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -117,16 +117,16 @@ struct sdb_session { char native_lanman[SMB_PI_MAX_LANMAN]; int sock; short port; - unsigned short secmode; + uint16_t secmode; uint32_t sesskey; uint32_t challenge_len; - unsigned char challenge_key[32]; - unsigned char smb_flags; - unsigned short smb_flags2; - unsigned short vc; + uint8_t challenge_key[32]; + uint8_t smb_flags; + uint16_t smb_flags2; + uint16_t vc; uint32_t remote_caps; - unsigned short state; - unsigned int sid; /* session id */ + uint8_t state; + uint32_t sid; /* session id */ int remote_os; int remote_lm; int pdc_type; @@ -208,12 +208,12 @@ void smbrdr_session_unlock(struct sdb_session *); /* * smbrdr_logon.c */ -int smbrdr_smb_logoff(struct sdb_logon *); +int smbrdr_logoffx(struct sdb_logon *); /* smbrdr_netuse.c */ void smbrdr_netuse_logoff(unsigned short); struct sdb_netuse *smbrdr_netuse_get(int); -unsigned short mlsvc_tree_connect(char *, char *, char *); +unsigned short smbrdr_tree_connect(char *, char *, char *); int smbrdr_tree_disconnect(unsigned short); void smbrdr_netuse_put(struct sdb_netuse *); @@ -232,8 +232,8 @@ DWORD smbrdr_rcv(smbrdr_handle_t *, int); DWORD smbrdr_exchange(smbrdr_handle_t *, smb_hdr_t *, long); void smbrdr_handle_free(smbrdr_handle_t *); int smbrdr_sign_init(struct sdb_session *, struct sdb_logon *); -int smbrdr_sign_fini(struct sdb_session *); -int smbrdr_sign_unset_key(struct sdb_session *); +void smbrdr_sign_fini(struct sdb_session *); +void smbrdr_sign_unset_key(struct sdb_session *); void smbrdr_lock_transport(void); void smbrdr_unlock_transport(void); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c index cbce43db5e..8185ddee5e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_ipc_util.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,11 +34,9 @@ #include <string.h> #include <strings.h> -#include <syslog.h> #include <synch.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/mlsvc.h> #include <smbsrv/smbinfo.h> #include <smbrdr.h> @@ -53,20 +51,17 @@ static smbrdr_ipc_t orig_ipc_info; static int smbrdr_get_machine_pwd_hash(unsigned char *hash) { - char *pwd; + char pwd[SMB_PI_MAX_PASSWD]; int rc = 0; - smb_config_rdlock(); - pwd = smb_config_getstr(SMB_CI_MACHINE_PASSWD); - if (!pwd || *pwd == 0) { - smb_config_unlock(); + rc = smb_config_getstr(SMB_CI_MACHINE_PASSWD, pwd, sizeof (pwd)); + if ((rc != SMBD_SMF_OK) || *pwd == '\0') { return (-1); } - if (smb_auth_ntlm_hash((char *)pwd, hash) != 0) + if (smb_auth_ntlm_hash(pwd, hash) != 0) rc = -1; - smb_config_unlock(); return (rc); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c index ac4743548c..432d66141e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_lib.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,17 +36,12 @@ #include <smbsrv/ntstatus.h> #include <smbrdr.h> -static DWORD smbrdr_handle_setup(smbrdr_handle_t *srh, unsigned char cmd, - struct sdb_session *session, struct sdb_logon *logon, - struct sdb_netuse *netuse); - -static int smbrdr_hdr_setup(smbrdr_handle_t *srh); - -static DWORD smbrdr_hdr_process(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr); - -static int smbrdr_sign(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb); -static int smbrdr_sign_chk(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb, - unsigned char *signature); +static DWORD smbrdr_handle_setup(smbrdr_handle_t *, unsigned char, + struct sdb_session *, struct sdb_logon *, struct sdb_netuse *); +static int smbrdr_hdr_setup(smbrdr_handle_t *); +static DWORD smbrdr_hdr_process(smbrdr_handle_t *, smb_hdr_t *); +static int smbrdr_sign(smb_sign_ctx_t *, smb_msgbuf_t *); +static int smbrdr_sign_chk(smb_sign_ctx_t *, smb_msgbuf_t *, unsigned char *); void smbrdr_lock_transport() { nb_lock(); } void smbrdr_unlock_transport() { nb_unlock(); } @@ -73,13 +68,10 @@ smbrdr_request_init(smbrdr_handle_t *srh, DWORD status; status = smbrdr_handle_setup(srh, cmd, session, logon, netuse); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_DEBUG, "Smbrdr[%d]: initialization failed", cmd); + if (status != NT_STATUS_SUCCESS) return (status); - } if (smbrdr_hdr_setup(srh) < SMB_HEADER_LEN) { - syslog(LOG_DEBUG, "Smbrdr[%d]: cannot setup header", cmd); smbrdr_handle_free(srh); return (NT_STATUS_INTERNAL_ERROR); } @@ -105,8 +97,11 @@ smbrdr_send(smbrdr_handle_t *srh) int rc; if (smbrdr_sign(&srh->srh_session->sign_ctx, &srh->srh_mbuf) != - SMBAUTH_SUCCESS) + SMBAUTH_SUCCESS) { + syslog(LOG_DEBUG, "smbrdr_send[%d]: signing failed", + srh->srh_cmd); return (NT_STATUS_INTERNAL_ERROR); + } rc = nb_send(srh->srh_session->sock, srh->srh_buf, smb_msgbuf_used(&srh->srh_mbuf)); @@ -163,7 +158,6 @@ smbrdr_rcv(smbrdr_handle_t *srh, int is_first_rsp) return (NT_STATUS_UNEXPECTED_NETWORK_ERROR); } - /* initialize for processing response */ smb_msgbuf_init(&srh->srh_mbuf, srh->srh_buf, rc, srh->srh_mbflags); status = smbrdr_hdr_process(srh, &smb_hdr); @@ -177,7 +171,7 @@ smbrdr_rcv(smbrdr_handle_t *srh, int is_first_rsp) if (!smbrdr_sign_chk(sign_ctx, &srh->srh_mbuf, smb_hdr.extra.extra.security_sig)) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: bad signature", + syslog(LOG_DEBUG, "smbrdr_rcv[%d]: bad signature", srh->srh_cmd); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } @@ -217,15 +211,18 @@ smbrdr_exchange(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr, long timeout) mb = &srh->srh_mbuf; sign_ctx = &srh->srh_session->sign_ctx; - if (smbrdr_sign(sign_ctx, mb) != SMBAUTH_SUCCESS) + if (smbrdr_sign(sign_ctx, mb) != SMBAUTH_SUCCESS) { + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: signing failed", + srh->srh_cmd); return (NT_STATUS_INTERNAL_ERROR); + } rc = nb_exchange(srh->srh_session->sock, srh->srh_buf, smb_msgbuf_used(mb), srh->srh_buf, SMBRDR_REQ_BUFSZ, timeout); if (rc < 0) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: failed (%d)", + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: failed (%d)", srh->srh_cmd, rc); if (srh->srh_cmd != SMB_COM_ECHO) { @@ -251,7 +248,7 @@ smbrdr_exchange(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr, long timeout) /* Signature validation */ if (!smbrdr_sign_chk(sign_ctx, mb, smb_hdr->extra.extra.security_sig)) { - syslog(LOG_ERR, "SmbrdrExchange[%d]: bad signature", + syslog(LOG_DEBUG, "smbrdr_exchange[%d]: bad signature", srh->srh_cmd); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } @@ -313,14 +310,12 @@ smbrdr_sign_init(struct sdb_session *session, struct sdb_logon *logon) if ((sign_ctx->ssc_flags & SMB_SCF_REQUIRED) && !(sign_ctx->ssc_flags & SMB_SCF_STARTED) && (logon->type != SDB_LOGON_ANONYMOUS)) { - if (smb_mac_init(sign_ctx, &logon->auth) != SMBAUTH_SUCCESS) { - syslog(LOG_DEBUG, "SmbrdrSignInit: mac_init failed"); + if (smb_mac_init(sign_ctx, &logon->auth) != SMBAUTH_SUCCESS) return (-1); - } + sign_ctx->ssc_flags |= (SMB_SCF_STARTED | SMB_SCF_KEY_ISSET_THIS_LOGON); session->smb_flags2 |= SMB_FLAGS2_SMB_SECURITY_SIGNATURE; - syslog(LOG_DEBUG, "SmbrdrSignInit: mac key is set"); rc = 1; } @@ -333,23 +328,16 @@ smbrdr_sign_init(struct sdb_session *session, struct sdb_logon *logon) * Invalidate the MAC key if the first non-anonymous/non-guest user logon * fail. */ -int +void smbrdr_sign_fini(struct sdb_session *session) { - smb_sign_ctx_t *sign_ctx; - int rc = 0; - - sign_ctx = &session->sign_ctx; + smb_sign_ctx_t *sign_ctx = &session->sign_ctx; if (sign_ctx->ssc_flags & SMB_SCF_KEY_ISSET_THIS_LOGON) { sign_ctx->ssc_flags &= ~SMB_SCF_STARTED; sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; sign_ctx->ssc_seqnum = 0; - syslog(LOG_DEBUG, "SmbrdrSignFini: packet signing stopped"); - rc = 1; } - - return (rc); } /* @@ -359,21 +347,12 @@ smbrdr_sign_fini(struct sdb_session *session) * SmbSessionSetupAndX request for the first non-anonymous/non-guest * logon. */ -int +void smbrdr_sign_unset_key(struct sdb_session *session) { - smb_sign_ctx_t *sign_ctx; - int rc = 0; - - sign_ctx = &session->sign_ctx; - - if (sign_ctx->ssc_flags & SMB_SCF_KEY_ISSET_THIS_LOGON) { - sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; - syslog(LOG_DEBUG, "SmbrdrSignUnsetKey: unset KEY_ISSET flag"); - rc = 1; - } + smb_sign_ctx_t *sign_ctx = &session->sign_ctx; - return (rc); + sign_ctx->ssc_flags &= ~SMB_SCF_KEY_ISSET_THIS_LOGON; } /* @@ -396,10 +375,9 @@ smbrdr_handle_setup(smbrdr_handle_t *srh, struct sdb_netuse *netuse) { srh->srh_buf = (unsigned char *)malloc(SMBRDR_REQ_BUFSZ); - if (srh->srh_buf == 0) { - syslog(LOG_ERR, "Smbrdr[%d]: resource shortage", cmd); + if (srh->srh_buf == NULL) return (NT_STATUS_NO_MEMORY); - } + bzero(srh->srh_buf, SMBRDR_REQ_BUFSZ); srh->srh_mbflags = (session->remote_caps & CAP_UNICODE) @@ -468,6 +446,10 @@ smb_decode_nt_hdr(smb_msgbuf_t *mb, smb_hdr_t *hdr) * Assuming 'srh->srh_mbuf' contains a response from a Windows client, * decodes the 32 bytes SMB header. * + * Buffer overflow typically means that the server has more data than + * it could fit in the response buffer. The client can use subsequent + * SmbReadX requests to obtain the remaining data (KB 193839). + * * Returns: * * NT_STATUS_INVALID_NETWORK_RESPONSE error decoding the header @@ -480,43 +462,26 @@ smbrdr_hdr_process(smbrdr_handle_t *srh, smb_hdr_t *smb_hdr) { int rc; - /* - * Returns the number of decoded bytes on success - * or some negative MSGBUF_XXX error code on failure - */ rc = smb_decode_nt_hdr(&srh->srh_mbuf, smb_hdr); - if (rc < SMB_HEADER_LEN) { - syslog(LOG_ERR, "Smbrdr[%d]: bad SMB header (%d)", + syslog(LOG_DEBUG, "smbrdr[%d]: invalid header (%d)", srh->srh_cmd, rc); return (NT_STATUS_INVALID_NETWORK_RESPONSE); } - if (smb_hdr->status.ntstatus != 0) { - /* - * MSDN article: 193839 - * "The buffer overflow status is usually returned by a Windows - * server to inform the client that there is more data in its - * buffer than it could put in the packet. - * - * The buffer overflow should not be considered as an error. - * Subsequent SmbReadX request is required to obtain the - * remaining data in the server's buffer. - */ - if (NT_SC_VALUE(smb_hdr->status.ntstatus) - == NT_STATUS_BUFFER_OVERFLOW) { - syslog(LOG_DEBUG, "Smbrdr[%d]: %s", srh->srh_cmd, - xlate_nt_status(smb_hdr->status.ntstatus)); - } else { - syslog(LOG_ERR, "Smbrdr[%d]: request failed (%s)", - srh->srh_cmd, - xlate_nt_status(smb_hdr->status.ntstatus)); - return (smb_hdr->status.ntstatus); - } + switch (NT_SC_VALUE(smb_hdr->status.ntstatus)) { + case NT_STATUS_SUCCESS: + case NT_STATUS_BUFFER_OVERFLOW: + break; + + default: + syslog(LOG_DEBUG, "smbrdr[%d]: request failed (%s)", + srh->srh_cmd, xlate_nt_status(smb_hdr->status.ntstatus)); + return (smb_hdr->status.ntstatus); } if (smb_hdr->command != srh->srh_cmd) { - syslog(LOG_ERR, "Smbrdr[%d]: reply mismatch (%d)", + syslog(LOG_DEBUG, "smbrdr[%d]: reply mismatch (%d)", srh->srh_cmd, smb_hdr->command); return (NT_STATUS_REPLY_MESSAGE_MISMATCH); } @@ -551,8 +516,7 @@ smbrdr_sign(smb_sign_ctx_t *sign_ctx, smb_msgbuf_t *mb) { if (sign_ctx->ssc_flags & SMB_SCF_STARTED) { if (sign_ctx->ssc_seqnum % 2) { - syslog(LOG_DEBUG, "SmbrdrSign: even sequence number" - " is expected(%d)", + syslog(LOG_DEBUG, "smbrdr_sign: invalid sequence (%d)", sign_ctx->ssc_seqnum); } if (smb_mac_sign(sign_ctx, smb_msgbuf_base(mb), diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c index d33f253b29..374afe8c6f 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_logon.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include <strings.h> #include <syslog.h> #include <synch.h> +#include <sys/errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -44,10 +45,10 @@ #include <smbrdr_ipc_util.h> #include <smbrdr.h> -static int mlsvc_anonymous_logon(char *domain_controller, char *domain_name); -static int mlsvc_auth_logon(char *domain_controller, char *domain_name, - char *username, unsigned char *pwd_hash); -static int smbrdr_smb_session_setupandx(struct sdb_logon *logon); +static int smbrdr_anonymous_logon(char *domain_controller, char *domain_name); +static int smbrdr_auth_logon(char *domain_controller, char *domain_name, + char *username); +static int smbrdr_session_setupx(struct sdb_logon *logon); static boolean_t smbrdr_logon_validate(char *server, char *username); static struct sdb_logon *smbrdr_logon_init(struct sdb_session *session, char *username, unsigned char *pwd); @@ -58,7 +59,7 @@ static int smbrdr_authenticate(char *primary_domain, char *account_name, /* * mlsvc_logon * - * If the username is NULL, an anonymous session will be established. + * 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. */ @@ -66,48 +67,39 @@ int mlsvc_logon(char *domain_controller, char *domain, char *username) { int rc; - unsigned char *pwd_hash = NULL; - if (username) { - pwd_hash = smbrdr_ipc_get_passwd(); - rc = mlsvc_auth_logon(domain_controller, domain, username, - pwd_hash); - } else { - rc = mlsvc_anonymous_logon(domain_controller, domain); - } + if (strcmp(username, MLSVC_ANON_USER) == 0) + rc = smbrdr_anonymous_logon(domain_controller, domain); + else + rc = smbrdr_auth_logon(domain_controller, domain, username); return (rc); } /* - * mlsvc_anonymous_logon + * smbrdr_anonymous_logon * * Set up an anonymous session. If the session to the resource domain * controller appears to be okay we shouldn't need to do anything here. * Otherwise we clean up the stale session and create a new one. */ static int -mlsvc_anonymous_logon(char *domain_controller, char *domain_name) +smbrdr_anonymous_logon(char *domain_controller, char *domain_name) { - int rc = 0; - if (smbrdr_logon_validate(domain_controller, MLSVC_ANON_USER)) - /* session & user are good use them */ return (0); - if (smbrdr_negotiate(domain_name) != 0) { - syslog(LOG_ERR, "smbrdr: (anon logon) negotiate <%s> failed", - (domain_name ? domain_name : "NoName")); + syslog(LOG_DEBUG, "smbrdr_anonymous_logon: negotiate failed"); return (-1); } if (smbrdr_logon_user(domain_controller, MLSVC_ANON_USER, 0) < 0) { - syslog(LOG_ERR, "smbrdr: (anon logon) logon failed"); - rc = -1; + syslog(LOG_DEBUG, "smbrdr_anonymous_logon: logon failed"); + return (-1); } - return (rc); + return (0); } int @@ -131,7 +123,7 @@ mlsvc_user_getauth(char *domain_controller, char *username, } /* - * mlsvc_auth_logon + * smbrdr_auth_logon * * Set up a user session. If the session to the resource domain controller * appears to be okay we shouldn't need to do anything here. Otherwise we @@ -140,18 +132,19 @@ mlsvc_user_getauth(char *domain_controller, char *username, * due to an inactivity timeout or a domain controller reset. */ static int -mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username, - unsigned char *pwd_hash) +smbrdr_auth_logon(char *domain_controller, char *domain_name, char *username) { int erc; + unsigned char *pwd_hash = NULL; if (username == NULL || *username == 0) { - syslog(LOG_ERR, "smbrdr: auth logon (no username)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: no username"); return (-1); } + pwd_hash = smbrdr_ipc_get_passwd(); if (!pwd_hash || *pwd_hash == 0) { - syslog(LOG_ERR, "smbrdr: auth logon (no password)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: no password"); return (-1); } @@ -159,7 +152,7 @@ mlsvc_auth_logon(char *domain_controller, char *domain_name, char *username, return (0); if (smbrdr_negotiate(domain_name) != 0) { - syslog(LOG_ERR, "smbrdr: admin logon (negotiate failed)"); + syslog(LOG_DEBUG, "smbrdr_auth_logon: negotiate failed"); return (-1); } @@ -189,7 +182,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name, if ((di = smb_getdomaininfo(0)) == 0) { - syslog(LOG_ERR, "MlsvcAuthenticate[%s]: %s", account_name, + syslog(LOG_DEBUG, "smbrdr_authenticate[%s]: %s", account_name, xlate_nt_status(NT_STATUS_CANT_ACCESS_DOMAIN_INFO)); return (-1); } @@ -211,7 +204,7 @@ smbrdr_authenticate(char *primary_domain, char *account_name, * to the resource domain. */ if (strcasecmp(di->domain, primary_domain)) { - syslog(LOG_ERR, "MlsvcAuthenticate: %s\\%s: not account domain", + syslog(LOG_DEBUG, "smbrdr_authenticate: %s\\%s: invalid domain", primary_domain, account_name); return (-2); } @@ -225,9 +218,9 @@ smbrdr_authenticate(char *primary_domain, char *account_name, * This is the entry point for logging a user onto the domain. The * session structure should have been obtained via a successful call * to smbrdr_smb_connect. We allocate a logon structure to hold the - * user details and attempt to logon using smbrdr_smb_session_setupandx. Note - * that we expect the password fields to have been encrypted before - * this call. + * user details and attempt to logon using smbrdr_session_setupx. + * Note that we expect the password fields to have been encrypted + * before this call. * * On success, the logon structure will be returned. Otherwise a null * pointer will be returned. @@ -245,8 +238,8 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) } session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE); - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (logon[%s]) no session with %s", + if (session == NULL) { + syslog(LOG_DEBUG, "smbrdr_logon_user: %s: no session with %s", username, server); return (-1); } @@ -267,14 +260,14 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) logon = smbrdr_logon_init(session, username, pwd); - if (logon == 0) { - syslog(LOG_ERR, "smbrdr: (logon[%s]) resource shortage", - username); + if (logon == NULL) { + syslog(LOG_DEBUG, "smbrdr_logon_user: %s: %s", + username, strerror(ENOMEM)); smbrdr_session_unlock(session); return (-1); } - if (smbrdr_smb_session_setupandx(logon) < 0) { + if (smbrdr_session_setupx(logon) < 0) { free(logon); smbrdr_session_unlock(session); return (-1); @@ -284,7 +277,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) free(logon); if (old_logon.type != SDB_LOGON_NONE) { - (void) smbrdr_smb_logoff(&old_logon); + (void) smbrdr_logoffx(&old_logon); } smbrdr_session_unlock(session); @@ -294,7 +287,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) /* - * smbrdr_smb_session_setupandx + * smbrdr_session_setupx * * Build and send an SMB session setup command. This is used to log a * user onto the domain. See CIFS section 4.1.2. @@ -302,7 +295,7 @@ smbrdr_logon_user(char *server, char *username, unsigned char *pwd) * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_session_setupandx(struct sdb_logon *logon) +smbrdr_session_setupx(struct sdb_logon *logon) { struct sdb_session *session; smb_hdr_t smb_hdr; @@ -322,10 +315,8 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) * Paranoia check - we should never get this * far without a valid session structure. */ - if ((session = logon->session) == 0) { - syslog(LOG_ERR, "smbrdr_smb_session_setupandx: no data"); + if ((session = logon->session) == NULL) return (-1); - } if (session->remote_caps & CAP_UNICODE) { strlen_fn = mts_wcequiv_strlen; @@ -336,15 +327,18 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) null_size = sizeof (char); } - if (smbrdr_sign_init(session, logon) < 0) + if (smbrdr_sign_init(session, logon) < 0) { + syslog(LOG_DEBUG, + "smbrdr_session_setupx: smbrdr_sign_init failed"); return (-1); + } status = smbrdr_request_init(&srh, SMB_COM_SESSION_SETUP_ANDX, session, 0, 0); if (status != NT_STATUS_SUCCESS) { - (void) smbrdr_sign_fini(session); - syslog(LOG_ERR, "SmbrdrSessionSetup: %s", + smbrdr_sign_fini(session); + syslog(LOG_DEBUG, "smbrdr_session_setupx: %s", xlate_nt_status(status)); return (-1); } @@ -415,18 +409,18 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } if (rc <= 0) { - syslog(LOG_ERR, "smbrdr_smb_session_setupandx: encode failed"); + syslog(LOG_DEBUG, "smbrdr_session_setupx: encode failed"); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrSessionSetup: %s", + syslog(LOG_DEBUG, "smbrdr_session_setupx: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } @@ -461,9 +455,9 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } if (rc <= 0) { - syslog(LOG_ERR, "RdrSessionSetup: decode failed"); + syslog(LOG_DEBUG, "smbrdr_session_setupx: decode failed"); smbrdr_handle_free(&srh); - (void) smbrdr_sign_fini(session); + smbrdr_sign_fini(session); return (-1); } @@ -476,7 +470,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) logon->type = SDB_LOGON_GUEST; smbrdr_handle_free(&srh); - (void) smbrdr_sign_unset_key(session); + smbrdr_sign_unset_key(session); logon->state = SDB_LSTATE_SETUP; @@ -484,7 +478,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) } /* - * smbrdr_smb_logoff + * smbrdr_logoffx * * Build and send an SMB session logoff (SMB_COM_LOGOFF_ANDX) command. * This is the inverse of an SMB_COM_SESSION_SETUP_ANDX. See CIFS @@ -494,7 +488,7 @@ smbrdr_smb_session_setupandx(struct sdb_logon *logon) * Returns 0 on success. Otherwise returns a -ve error code. */ int -smbrdr_smb_logoff(struct sdb_logon *logon) +smbrdr_logoffx(struct sdb_logon *logon) { struct sdb_session *session; smbrdr_handle_t srh; @@ -527,7 +521,7 @@ smbrdr_smb_logoff(struct sdb_logon *logon) if (status != NT_STATUS_SUCCESS) { logon->state = SDB_LSTATE_SETUP; - syslog(LOG_ERR, "smbrdr: logoff %s (%s)", logon->username, + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: %s", logon->username, xlate_nt_status(status)); return (-1); } @@ -536,14 +530,14 @@ smbrdr_smb_logoff(struct sdb_logon *logon) if (rc < 0) { logon->state = SDB_LSTATE_SETUP; smbrdr_handle_free(&srh); - syslog(LOG_ERR, "smbrdr: logoff %s (encode failed)", + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: encode failed", logon->username); return (rc); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: logoff %s (%s)", logon->username, + syslog(LOG_DEBUG, "smbrdr_logoffx: %s: %s", logon->username, xlate_nt_status(status)); rc = -1; } else { @@ -570,7 +564,7 @@ smbrdr_logon_init(struct sdb_session *session, char *username, unsigned char *pwd) { struct sdb_logon *logon; - int smbrdr_lmcompl; + int64_t smbrdr_lmcompl; int rc; logon = (struct sdb_logon *)malloc(sizeof (sdb_logon_t)); @@ -580,9 +574,7 @@ smbrdr_logon_init(struct sdb_session *session, char *username, bzero(logon, sizeof (struct sdb_logon)); logon->session = session; - smb_config_rdlock(); - smbrdr_lmcompl = smb_config_getnum(SMB_CI_LM_LEVEL); - smb_config_unlock(); + (void) smb_config_getnum(SMB_CI_LM_LEVEL, &smbrdr_lmcompl); if (strcmp(username, "IPC$") == 0) { logon->type = SDB_LOGON_ANONYMOUS; @@ -625,7 +617,8 @@ smbrdr_logon_validate(char *server, char *username) valid = B_TRUE; } else { session->state = SDB_SSTATE_STALE; - syslog(LOG_DEBUG, "smbrdr: (logon) stale session"); + syslog(LOG_DEBUG, + "smbrdr_logon_validate: stale session"); } smbrdr_session_unlock(session); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c index 2066dab051..756a816378 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netbios.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,6 @@ #include <string.h> #include <unistd.h> -#include <syslog.h> #include <synch.h> #include <sys/types.h> #include <sys/uio.h> @@ -128,8 +127,6 @@ nb_keep_alive(int fd) (void) mutex_lock(&nb_mutex); rc = nb_write_msg(fd, (unsigned char *)¬hing, 0, SESSION_KEEP_ALIVE); - if (rc < 0) - syslog(LOG_ERR, "nb_keep_alive: write failed"); (void) mutex_unlock(&nb_mutex); return (rc); @@ -145,9 +142,7 @@ nb_send(int fd, unsigned char *send_buf, unsigned send_cnt) { int rc; - if ((rc = nb_write_msg(fd, send_buf, send_cnt, SESSION_MESSAGE)) < 0) - syslog(LOG_ERR, "nb_send: write failed: rc=%d", rc); - + rc = nb_write_msg(fd, send_buf, send_cnt, SESSION_MESSAGE); return (rc); } @@ -166,16 +161,12 @@ nb_rcv(int fd, unsigned char *recv_buf, unsigned recv_max, long timeout) do { rc = nb_read_msg(fd, recv_buf, recv_max, &type, timeout); - if (rc < 0) { - syslog(LOG_ERR, "nb_rcv: read failed: rc=%d", rc); + if (rc < 0) return (rc); - } } while (type == SESSION_KEEP_ALIVE); - if (type != SESSION_MESSAGE) { - syslog(LOG_ERR, "nb_rcv: invalid type: %d", type); + if (type != SESSION_MESSAGE) return (NB_RCV_MSG_ERR_INVTYPE); - } return (rc); } @@ -236,8 +227,6 @@ nb_session_request(int fd, char *called_name, char *called_scope, rc = nb_write_msg(fd, (unsigned char *)sr_buf, len, SESSION_REQUEST); if (rc < 0) { - syslog(LOG_ERR, "nb_session_request: write failed:" - " rc=%d", rc); (void) mutex_unlock(&nb_mutex); return (rc); } @@ -287,7 +276,6 @@ nb_write_msg(int fd, unsigned char *buf, unsigned count, int type) /* * We should never see descriptor 0 (stdin). */ - syslog(LOG_ERR, "nb_write_msg: invalid descriptor (%d)", fd); return (-1); } @@ -310,7 +298,6 @@ nb_write_msg(int fd, unsigned char *buf, unsigned count, int type) rc = writev(fd, iov, 2); if (rc != 4 + count) { - syslog(LOG_ERR, "nb_write_msg: writev rc=%d", rc); return (-3); /* error */ } @@ -340,7 +327,6 @@ nb_read_msg(int fd, unsigned char *buf, unsigned max_buf, /* * We should never see descriptor 0 (stdin). */ - syslog(LOG_ERR, "nb_write_msg: invalid descriptor (%d)", fd); return (NB_READ_MSG_ERR); } @@ -350,7 +336,6 @@ nb_read_msg(int fd, unsigned char *buf, unsigned max_buf, tval.tv_usec = 0; if ((rc = select(fd + 1, &readfds, 0, 0, &tval)) <= 0) { - syslog(LOG_ERR, "nb_read_msg: select: %d", rc); return (NB_READ_MSG_ERR); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c index 508b258cd6..2cb74e66e8 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_netuse.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,6 +31,7 @@ * Specification (December 19, 1997). */ +#include <sys/errno.h> #include <string.h> #include <strings.h> #include <syslog.h> @@ -38,7 +39,6 @@ #include <pthread.h> #include <smbsrv/libsmbrdr.h> - #include <smbrdr.h> #include <smbsrv/ntstatus.h> @@ -48,12 +48,12 @@ */ static struct sdb_netuse netuse_table[N_NETUSE_TABLE]; -static int smbrdr_smb_tcon(struct sdb_session *session, +static int smbrdr_tree_connectx(struct sdb_session *session, struct sdb_netuse *netuse, char *path, int path_len); static struct sdb_netuse *smbrdr_netuse_alloc(struct sdb_session *session, char *sharename); -static int smbrdr_smb_tdcon(struct sdb_netuse *netuse); +static int smbrdr_tdcon(struct sdb_netuse *netuse); static void smbrdr_netuse_clear(struct sdb_netuse *netuse) @@ -69,19 +69,19 @@ smbrdr_netuse_free(struct sdb_netuse *netuse) } /* - * mlsvc_tree_connect + * smbrdr_tree_connect * * Establish a share (tree connect). We need to retrieve the session * for the specified host and allocate a netuse structure. We set up * the path here (UNC encoded) to make handling the malloc/free easier - * and pass everything on to smbrdr_smb_tcon where, if everything goes well, - * a valid tid will be stored in the netuse structure. + * and pass everything on to smbrdr_tree_connectx where. If everything + * goes well, a valid tid will be stored in the netuse structure. * * On success, a pointer to the netuse is returned. Otherwise the * netuse is cleared and a null pointer is returned. */ unsigned short -mlsvc_tree_connect(char *hostname, char *username, char *sharename) +smbrdr_tree_connect(char *hostname, char *username, char *sharename) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -92,15 +92,15 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) * Make sure there is a session & logon for given info */ session = smbrdr_session_lock(hostname, username, SDB_SLCK_READ); - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) no session for %s@%s", + if (session == NULL) { + syslog(LOG_DEBUG, "smbrdr_tree_connect: no session for %s@%s", username, hostname); return (0); } if ((netuse = smbrdr_netuse_alloc(session, sharename)) == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) init failed"); + syslog(LOG_DEBUG, "smbrdr_tree_connect: init failed"); smbrdr_session_unlock(session); return (0); } @@ -114,7 +114,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) if ((path = (char *)malloc(path_len)) == 0) { smbrdr_netuse_free(netuse); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: (tcon) resource shortage"); + syslog(LOG_DEBUG, "smbrdr_tree_connect: %s", strerror(ENOMEM)); return (0); } @@ -125,11 +125,11 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) else path_len = strlen(path); - if (smbrdr_smb_tcon(session, netuse, path, path_len) < 0) { + if (smbrdr_tree_connectx(session, netuse, path, path_len) < 0) { smbrdr_netuse_free(netuse); smbrdr_session_unlock(session); free(path); - syslog(LOG_ERR, "smbrdr: (tcon) failed connecting to %s", path); + syslog(LOG_DEBUG, "smbrdr_tree_connect: %s failed", path); return (0); } @@ -141,7 +141,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) /* - * smbrdr_smb_tcon + * smbrdr_tree_connectx * * This message requests a share (tree connect) request to the server * associated with the session. The password is not relevant here if @@ -151,7 +151,7 @@ mlsvc_tree_connect(char *hostname, char *username, char *sharename) * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, +smbrdr_tree_connectx(struct sdb_session *session, struct sdb_netuse *netuse, char *path, int path_len) { smb_hdr_t smb_hdr; @@ -170,7 +170,8 @@ smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, session, &session->logon, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTcon: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tree_connectx: %s", + xlate_nt_status(status)); return (-1); } @@ -202,26 +203,25 @@ smbrdr_smb_tcon(struct sdb_session *session, struct sdb_netuse *netuse, service); /* Service */ if (rc <= 0) { - syslog(LOG_ERR, "smbrdr_smb_tcon: encode failed"); + syslog(LOG_DEBUG, "smbrdr_tree_connectx: encode failed"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTcon: %s", xlate_nt_status(status)); - rc = -1; - } else { - rc = 0; + syslog(LOG_DEBUG, "smbrdr_tree_connectx: %s", + xlate_nt_status(status)); + smbrdr_handle_free(&srh); + return (-1); } netuse->tid = smb_hdr.tid; netuse->state = SDB_NSTATE_CONNECTED; smbrdr_handle_free(&srh); - return (rc); + return (0); } - /* * smbrdr_netuse_logoff * @@ -242,7 +242,7 @@ smbrdr_netuse_logoff(unsigned short uid) netuse = &netuse_table[i]; (void) mutex_lock(&netuse->mtx); if (netuse->uid == uid) - (void) smbrdr_smb_tdcon(netuse); + (void) smbrdr_tdcon(netuse); (void) mutex_unlock(&netuse->mtx); } } @@ -255,7 +255,7 @@ smbrdr_tree_disconnect(unsigned short tid) netuse = smbrdr_netuse_get(tid); if (netuse) { - (void) smbrdr_smb_tdcon(netuse); + (void) smbrdr_tdcon(netuse); smbrdr_netuse_put(netuse); rc = 0; } @@ -264,17 +264,17 @@ smbrdr_tree_disconnect(unsigned short tid) } /* - * smbrdr_smb_tdcon + * smbrdr_tdcon * * Disconnect a share. This message informs the server that we no longer * wish to access the resource specified by tid, obtained via a prior - * mlsvc_tree_connect. The tid is passed in the SMB header so the setup + * smbrdr_tree_connect. The tid is passed in the SMB header so the setup * for this call is very straightforward. * * Returns 0 on success. Otherwise returns a -ve error code. */ static int -smbrdr_smb_tdcon(struct sdb_netuse *netuse) +smbrdr_tdcon(struct sdb_netuse *netuse) { struct sdb_session *session; smbrdr_handle_t srh; @@ -285,7 +285,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) netuse->state = SDB_NSTATE_DISCONNECTING; smbrdr_ofile_end_of_share(netuse->tid); - if ((session = netuse->session) == 0) { + if ((session = netuse->session) == NULL) { smbrdr_netuse_clear(netuse); return (0); } @@ -300,7 +300,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) session, &session->logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: (tdcon) %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tdcon: %s", xlate_nt_status(status)); /* should we clear here? */ smbrdr_netuse_clear(netuse); return (-1); @@ -308,7 +308,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) rc = smb_msgbuf_encode(&srh.srh_mbuf, "bw.", 0, 0); if (rc < 0) { - syslog(LOG_ERR, "smbrdr: (tdcon) encode failed"); + syslog(LOG_DEBUG, "smbrdr_tdcon: encode failed"); smbrdr_handle_free(&srh); /* should we clear here? */ smbrdr_netuse_clear(netuse); @@ -317,7 +317,7 @@ smbrdr_smb_tdcon(struct sdb_netuse *netuse) status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: (tdcon) %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_tdcon: %s", xlate_nt_status(status)); rc = -1; } else { rc = 0; @@ -347,10 +347,8 @@ smbrdr_netuse_alloc(struct sdb_session *session, char *sharename) struct sdb_netuse *netuse; int i; - if (session == 0 || sharename == 0) { - syslog(LOG_ERR, "smbrdr: (tcon) invalid arg"); - return (0); - } + if (session == NULL || sharename == NULL) + return (NULL); for (i = 0; i < N_NETUSE_TABLE; ++i) { netuse = &netuse_table[i]; @@ -369,7 +367,7 @@ smbrdr_netuse_alloc(struct sdb_session *session, char *sharename) (void) mutex_unlock(&netuse->mtx); } - syslog(LOG_WARNING, "smbrdr: (tcon) table full"); + syslog(LOG_DEBUG, "smbrdr_netuse_alloc: table full"); return (0); } @@ -431,7 +429,7 @@ smbrdr_netuse_get(int tid) (void) mutex_unlock(&netuse->mtx); } - syslog(LOG_WARNING, "smbrdr: (lookup) no such TID %d", tid); + syslog(LOG_DEBUG, "smbrdr_netuse_get: %d: no such TID", tid); return (0); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c index ef90fa79ac..3b2fc4dd7a 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_read_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,6 @@ #include <strings.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/netbios.h> #include <smbsrv/ntstatus.h> #include <smbrdr.h> @@ -46,15 +45,13 @@ static int smbrdr_decode_readx_rsp(smb_msgbuf_t *, char *, unsigned, smb_read_andx_rsp_t *); -static void smbrdr_dump_readx_rsp(smb_read_andx_rsp_t *); - /* - * smbrdr_rpc_readx + * smbrdr_readx * * Send SMB_COM_READ_ANDX request. */ int -smbrdr_rpc_readx(int fid, char *in_buf, int in_len) +smbrdr_readx(int fid, char *in_buf, int in_len) { struct sdb_netuse *netuse; struct sdb_ofile *ofile; @@ -64,7 +61,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) DWORD status; int rc, max_return; - if ((ofile = smbrdr_ofile_get(fid)) == 0) + if ((ofile = smbrdr_ofile_get(fid)) == NULL) return (-1); netuse = ofile->netuse; @@ -73,7 +70,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) netuse->session, &netuse->session->logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrReadAndx: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_readx: %s", xlate_nt_status(status)); smbrdr_ofile_put(ofile); return (-1); } @@ -104,7 +101,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) 0); /* Count of data bytes = 0 */ if (rc < 0) { - syslog(LOG_ERR, "SmbrdrReadAndx: smbrdr_prep_readx_req failed"); + syslog(LOG_DEBUG, "smbrdr_readx: prep failed"); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); return (rc); @@ -117,14 +114,14 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); - syslog(LOG_ERR, "SmbrdrReadAndx: send failed"); + syslog(LOG_DEBUG, "smbrdr_readx: send failed"); return (-1); } status = smbrdr_rcv(&srh, 1); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrReadAndx: nb_rcv failed"); + syslog(LOG_DEBUG, "smbrdr_readx: nb_rcv failed"); smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); @@ -134,7 +131,7 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) rc = smbrdr_decode_readx_rsp(mb, in_buf, in_len, &rsp); if (rc < 0) { - syslog(LOG_ERR, "SmbrdrReadAndx: read decode failure!"); + syslog(LOG_DEBUG, "smbrdr_readx: decode failed"); smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); @@ -148,20 +145,6 @@ smbrdr_rpc_readx(int fid, char *in_buf, int in_len) return ((rc < 0) ? rc : rsp.DataLength); } -static void -smbrdr_dump_readx_rsp(smb_read_andx_rsp_t *rsp) -{ - - syslog(LOG_DEBUG, "[SmbReadX Rsp] WordCount:%x,AndXCmd:%x," - " AndXReserved:%x, AndXOffset:%d", - rsp->WordCount, rsp->AndXCmd, rsp->AndXReserved, rsp->AndXOffset); - - syslog(LOG_DEBUG, "[SmbReadX Rsp] Remaining:%d, Mode:%d, Reserved:%x, " - "DataLen:%d, DataOffset:%d, ByteCount: %d", - rsp->Remaining, rsp->DataCompactionMode, rsp->Reserved, - rsp->DataLength, rsp->DataOffset, rsp->ByteCount); -} - /* * smbrdr_decode_readx_rsp * @@ -198,9 +181,6 @@ smbrdr_decode_readx_rsp(smb_msgbuf_t *mb, if (rc <= 0) return (-1); - smbrdr_dump_readx_rsp(rsp); - - /* it should never happen, but check anyway */ if (rsp->DataLength > in_len) return (-1); diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c index b89eddf275..3059a0cf0e 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_rpcpipe.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,14 +38,12 @@ #include <synch.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/ntstatus.h> #include <smbrdr.h> -static int smbrdr_smb_close(struct sdb_ofile *ofile); -static DWORD smbrdr_smb_ntcreate(struct sdb_ofile *ofile); -static struct sdb_ofile *smbrdr_ofile_alloc(struct sdb_netuse *netuse, - char *name); +static int smbrdr_close(struct sdb_ofile *); +static DWORD smbrdr_ntcreatex(struct sdb_ofile *); +static struct sdb_ofile *smbrdr_ofile_alloc(struct sdb_netuse *, char *); static void smbrdr_ofile_clear(struct sdb_ofile *ofile) @@ -86,24 +84,24 @@ mlsvc_open_pipe(char *hostname, char *domain, char *username, char *pipename) int retry; struct timespec st; - tid = mlsvc_tree_connect(hostname, username, "IPC$"); + tid = smbrdr_tree_connect(hostname, username, "IPC$"); if (tid == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_UNEXPECTED_NETWORK_ERROR)); return (-1); } netuse = smbrdr_netuse_get(tid); - if (netuse == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + if (netuse == NULL) { + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_CONNECTION_INVALID)); return (-1); } if ((ofile = smbrdr_ofile_alloc(netuse, pipename)) == 0) { - syslog(LOG_ERR, "smbrdr: (open) %s %s %s %s %s", + syslog(LOG_DEBUG, "smbrdr: (open) %s %s %s %s %s", hostname, domain, username, pipename, xlate_nt_status(NT_STATUS_INSUFFICIENT_RESOURCES)); smbrdr_netuse_put(netuse); @@ -113,7 +111,7 @@ mlsvc_open_pipe(char *hostname, char *domain, char *username, char *pipename) status = NT_STATUS_OPEN_FAILED; for (retry = 0; retry < mlsvc_pipe_recon_tries; retry++) { - status = smbrdr_smb_ntcreate(ofile); + status = smbrdr_ntcreatex(ofile); switch (status) { case NT_STATUS_SUCCESS: @@ -163,13 +161,11 @@ mlsvc_close_pipe(int fid) unsigned short tid; int rc; - if ((ofile = smbrdr_ofile_get(fid)) == 0) { - syslog(LOG_ERR, "mlsvc_close_pipe: unknown file (%d)", fid); + if ((ofile = smbrdr_ofile_get(fid)) == NULL) return (-1); - } tid = ofile->tid; - rc = smbrdr_smb_close(ofile); + rc = smbrdr_close(ofile); smbrdr_ofile_put(ofile); if (rc == 0) @@ -238,8 +234,7 @@ smbrdr_ofile_get(int fid) (void) mutex_unlock(&ofile->mtx); } - syslog(LOG_WARNING, "smbrdr: (lookup) no such FID %d", fid); - return (0); + return (NULL); } /* @@ -261,7 +256,7 @@ smbrdr_ofile_end_of_share(unsigned short tid) ofile = &ofile_table[i]; (void) mutex_lock(&ofile->mtx); if (ofile->tid == tid) - (void) smbrdr_smb_close(ofile); + (void) smbrdr_close(ofile); (void) mutex_unlock(&ofile->mtx); } } @@ -300,12 +295,12 @@ smbrdr_dump_ofiles() */ /* - * smbrdr_smb_close + * smbrdr_close * * Send SMBClose request for the given open file. */ static int -smbrdr_smb_close(struct sdb_ofile *ofile) +smbrdr_close(struct sdb_ofile *ofile) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -316,12 +311,12 @@ smbrdr_smb_close(struct sdb_ofile *ofile) int fid; int rc; - if (ofile == 0) + if (ofile == NULL) return (0); ofile->state = SDB_FSTATE_CLOSING; - if ((session = ofile->session) == 0) { + if ((session = ofile->session) == NULL) { smbrdr_ofile_clear(ofile); return (0); } @@ -341,20 +336,12 @@ smbrdr_smb_close(struct sdb_ofile *ofile) session, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrClose: %s", xlate_nt_status(status)); smbrdr_ofile_clear(ofile); return (-1); } - rc = smb_msgbuf_encode(&srh.srh_mbuf, - "(wct)b (fid)w (lwrtm)l (bcc)w (pad).", - 3, /* WordCount */ - fid, /* Fid */ - 0x00000000ul, /* LastWriteTime */ - 0); /* ByteCount */ - + rc = smb_msgbuf_encode(&srh.srh_mbuf, "bwlw.", 3, fid, 0x00000000ul, 0); if (rc <= 0) { - syslog(LOG_ERR, "SmbrdrClose: encode failed"); smbrdr_handle_free(&srh); smbrdr_ofile_clear(ofile); return (-1); @@ -362,7 +349,7 @@ smbrdr_smb_close(struct sdb_ofile *ofile) status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) - syslog(LOG_ERR, "SmbrdrClose: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_close: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); smbrdr_ofile_clear(ofile); @@ -405,19 +392,18 @@ smbrdr_ofile_alloc(struct sdb_netuse *netuse, char *name) (void) mutex_unlock(&ofile->mtx); } - syslog(LOG_WARNING, "smbrdr: (open) table full"); - return (0); + return (NULL); } /* - * smbrdr_smb_ntcreate + * smbrdr_ntcreatex * * This will do an SMB_COM_NT_CREATE_ANDX with lots of default values. * All of the underlying session and share data should already be set * up before we get here. If everything works we'll get a valid fid. */ static DWORD -smbrdr_smb_ntcreate(struct sdb_ofile *ofile) +smbrdr_ntcreatex(struct sdb_ofile *ofile) { struct sdb_logon *logon; struct sdb_netuse *netuse; @@ -458,13 +444,14 @@ smbrdr_smb_ntcreate(struct sdb_ofile *ofile) null_size = sizeof (char); } - syslog(LOG_DEBUG, "SmbRdrNtCreate: %d %s", path_len, path); + syslog(LOG_DEBUG, "smbrdr_ntcreatex: %d %s", path_len, path); status = smbrdr_request_init(&srh, SMB_COM_NT_CREATE_ANDX, sess, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrNtCreate: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_ntcreatex: %s", + xlate_nt_status(status)); return (NT_STATUS_INVALID_PARAMETER_1); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c index 535ad537d9..6bcba07778 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_session.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -61,38 +61,17 @@ static uint16_t smbrdr_ports[] = { static int smbrdr_nports = sizeof (smbrdr_ports) / sizeof (smbrdr_ports[0]); -/* - * Pointer to the PDC location interface. - * To be set up by SMB when it loads. - */ -static mlsvc_locate_pdc_t mlsvc_locate_pdc; - -/* - * This is a temporary hack to stop the DC from closing a session - * due to inactivity. - */ -#define MLSVC_SESSION_FORCE_KEEPALIVE 10 - -/* - * This is the session data table. - * - * The rwlock synchronizes access to the session table - * - * The mutex is to make session lookup and create atomic - * so we don't end up with two sessions with the same - * system. - */ static struct sdb_session session_table[MLSVC_DOMAIN_MAX]; static mutex_t smbrdr_screate_mtx; -static unsigned int session_id = 0; +static uint32_t session_id = 0; -static struct sdb_session *smbrdr_session_init(smb_ntdomain_t *di); +static struct sdb_session *smbrdr_session_init(smb_ntdomain_t *); static int smbrdr_trnsprt_connect(struct sdb_session *, uint16_t); -static int smbrdr_session_connect(smb_ntdomain_t *di); -static int smbrdr_smb_negotiate(struct sdb_session *session); -static int smbrdr_smb_echo(struct sdb_session *session); -static void smbrdr_session_disconnect(struct sdb_session *session, int cleanup); -static int smbrdr_locate_dc(char *domain); +static int smbrdr_session_connect(smb_ntdomain_t *); +static int smbrdr_smb_negotiate(struct sdb_session *); +static int smbrdr_echo(struct sdb_session *); +static void smbrdr_session_disconnect(struct sdb_session *, int); + static void smbrdr_session_clear(struct sdb_session *session) @@ -101,33 +80,6 @@ smbrdr_session_clear(struct sdb_session *session) } /* - * mlsvc_install_pdc_cb - * - * Function to be called by SMB initialization code to set up a - * callback to the PDC location interface. - */ -void -mlsvc_install_pdc_cb(mlsvc_locate_pdc_t locate_pdc_cb) -{ - mlsvc_locate_pdc = locate_pdc_cb; -} - -/* - * mlsvc_locate_domain_controller - * - * Locate a domain controller. Note that this may close an existing - * connection to the current domain controller. - */ -int -mlsvc_locate_domain_controller(char *domain) -{ - if (mlsvc_locate_pdc) - return (mlsvc_locate_pdc(domain)); - - return (0); -} - -/* * Entry pointy for smbrdr initialization. */ void @@ -168,25 +120,17 @@ mlsvc_disconnect(char *server) * * Returns 0 on success, otherwise -1. */ +/*ARGSUSED*/ int -smbrdr_negotiate(char *domain_name) +smbrdr_negotiate(char *domain) { struct sdb_session *session = 0; smb_ntdomain_t *di; int retry = 1; int res = 0; - if ((di = smb_getdomaininfo(0)) == 0) { - /* - * Attempting to locate a domain controller - * will shutdown an existing PDC connection. - */ - (void) smbrdr_locate_dc(domain_name); - di = smb_getdomaininfo(0); - } - - if (di == 0) { - syslog(LOG_ERR, "smbrdr: negotiate (cannot access domain)"); + if ((di = smb_getdomaininfo(0)) == NULL) { + syslog(LOG_DEBUG, "smbrdr_negotiate: cannot access domain"); return (-1); } @@ -198,7 +142,7 @@ smbrdr_negotiate(char *domain_name) (void) mutex_lock(&smbrdr_screate_mtx); while (retry > 0) { session = smbrdr_session_lock(di->server, 0, SDB_SLCK_WRITE); - if (session != 0) { + if (session != 0) { if (nb_keep_alive(session->sock) == 0) { /* session is good, use it */ smbrdr_session_unlock(session); @@ -212,12 +156,8 @@ smbrdr_negotiate(char *domain_name) if (smbrdr_session_connect(di) != 0) { if (retry > 0) { - /* Do we really need to do this here? */ - (void) smbrdr_locate_dc(domain_name); di = smb_getdomaininfo(0); - if (di == 0) { - syslog(LOG_ERR, "smbrdr: negotiate" - " (cannot access domain)"); + if (di == NULL) { res = -1; break; } @@ -230,6 +170,8 @@ smbrdr_negotiate(char *domain_name) } (void) mutex_unlock(&smbrdr_screate_mtx); + if (di == NULL) + syslog(LOG_DEBUG, "smbrdr_negotiate: cannot access domain"); return (res); } @@ -254,8 +196,8 @@ smbrdr_session_connect(smb_ntdomain_t *di) * be accessible until it's established otherwise another thread * might get access to a session which is not fully established. */ - if ((session = smbrdr_session_init(di)) == 0) { - syslog(LOG_ERR, "smbrdr: session init failed"); + if ((session = smbrdr_session_init(di)) == NULL) { + syslog(LOG_DEBUG, "smbrdr_session_init failed"); return (-1); } @@ -275,7 +217,7 @@ smbrdr_session_connect(smb_ntdomain_t *di) if (rc < 0) { smbrdr_session_clear(session); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: NBT/TCP connect failed"); + syslog(LOG_DEBUG, "smbrdr: connect failed"); return (-1); } @@ -283,7 +225,7 @@ smbrdr_session_connect(smb_ntdomain_t *di) (void) close(session->sock); smbrdr_session_clear(session); smbrdr_session_unlock(session); - syslog(LOG_ERR, "smbrdr: SMB negotiate failed"); + syslog(LOG_DEBUG, "smbrdr: negotiate failed"); return (-1); } @@ -313,11 +255,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) unsigned int cpid = oem_get_smb_cpid(); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0) { - /* - * We should never see descriptor 0 (stdin). - */ - syslog(LOG_ERR, "smbrdr: socket(%d) failed (%s)", sock, - strerror(errno)); + syslog(LOG_DEBUG, "smbrdr: socket failed: %s", strerror(errno)); return (-1); } @@ -327,7 +265,8 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) sin.sin_port = htons(port); if ((rc = connect(sock, (struct sockaddr *)&sin, sizeof (sin))) < 0) { - syslog(LOG_ERR, "smbrdr: connect failed (%s)", strerror(errno)); + syslog(LOG_DEBUG, "smbrdr: connect failed: %s", + strerror(errno)); if (sock != 0) (void) close(sock); return (-1); @@ -338,7 +277,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) rc = unicodestooems(server_name, unicode_server_name, SMB_PI_MAX_DOMAIN, cpid); if (rc == 0) { - syslog(LOG_ERR, "smbrdr: unicode conversion failed"); + syslog(LOG_DEBUG, "smbrdr: unicode conversion failed"); if (sock != 0) (void) close(sock); return (-1); @@ -352,7 +291,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) */ if (port == SSN_SRVC_TCP_PORT) { if (smb_getnetbiosname(hostname, MAXHOSTNAMELEN) != 0) { - syslog(LOG_ERR, "smbrdr: no hostname"); + syslog(LOG_DEBUG, "smbrdr: no hostname"); if (sock != 0) (void) close(sock); return (-1); @@ -362,7 +301,7 @@ smbrdr_trnsprt_connect(struct sdb_session *sess, uint16_t port) server_name, sess->scope, hostname, sess->scope); if (rc != 0) { - syslog(LOG_ERR, + syslog(LOG_DEBUG, "smbrdr: NBT session request to %s failed %d", server_name, rc); if (sock != 0) @@ -404,28 +343,19 @@ smbrdr_smb_negotiate(struct sdb_session *sess) status = smbrdr_request_init(&srh, SMB_COM_NEGOTIATE, sess, 0, 0); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: negotiate (%s)", - xlate_nt_status(status)); + if (status != NT_STATUS_SUCCESS) return (-1); - } mb = &srh.srh_mbuf; - rc = smb_msgbuf_encode(mb, "(wct)b (bcc)w (dialect)bs", - 0, /* smb_wct */ - 12, /* smb_bcc */ - 0x02, /* dialect marker */ - "NT LM 0.12"); /* only dialect we care about */ - + rc = smb_msgbuf_encode(mb, "bwbs", 0, 12, 0x02, "NT LM 0.12"); if (rc <= 0) { - syslog(LOG_ERR, "smbrdr: negotiate (encode failed)"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 0); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr: negotiate (%s)", + syslog(LOG_DEBUG, "smbrdr: negotiate: %s", xlate_nt_status(status)); smbrdr_handle_free(&srh); return (-1); @@ -436,12 +366,11 @@ smbrdr_smb_negotiate(struct sdb_session *sess) sess->challenge_len = 0; rc = smb_msgbuf_decode(mb, - "(wordcnt)1.(dialect)w(secm)b12.(skey)l(cap)l10.(klen)b2.", + "1.(dialect)w(mode)b12.(key)l(cap)l10.(keylen)b2.", &dialect, &tmp_secmode, &sess->sesskey, &sess->remote_caps, &tmp_clen); if (rc <= 0 || dialect != 0) { - syslog(LOG_ERR, "smbrdr: negotiate (response error)"); smbrdr_handle_free(&srh); return (-1); } @@ -451,7 +380,6 @@ smbrdr_smb_negotiate(struct sdb_session *sess) rc = smb_msgbuf_decode(mb, "#c", sess->challenge_len, sess->challenge_key); if (rc <= 0) { - syslog(LOG_ERR, "smbrdr: negotiate (decode error)"); smbrdr_handle_free(&srh); return (-1); } @@ -461,7 +389,7 @@ smbrdr_smb_negotiate(struct sdb_session *sess) if ((sess->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) && (sess->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { sess->sign_ctx.ssc_flags |= SMB_SCF_REQUIRED; - syslog(LOG_DEBUG, "smbrdr: %s requires signing", + syslog(LOG_DEBUG, "smbrdr: %s: signing required", sess->di.server); } @@ -482,12 +410,11 @@ smbrdr_smb_negotiate(struct sdb_session *sess) static struct sdb_session * smbrdr_session_init(smb_ntdomain_t *di) { - struct sdb_session *session = 0; + struct sdb_session *session = NULL; int i; - char *p; - if (di == 0) - return (0); + if (di == NULL) + return (NULL); for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { session = &session_table[i]; @@ -499,10 +426,8 @@ smbrdr_session_init(smb_ntdomain_t *di) (void) utf8_strupr(session->di.domain); (void) utf8_strupr(session->di.server); - smb_config_rdlock(); - p = smb_config_getstr(SMB_CI_NBSCOPE); - (void) strlcpy(session->scope, p, SMB_PI_MAX_SCOPE); - smb_config_unlock(); + (void) smb_config_getstr(SMB_CI_NBSCOPE, session->scope, + sizeof (session->scope)); (void) strlcpy(session->native_os, "Solaris", SMB_PI_MAX_NATIVE_OS); @@ -530,8 +455,8 @@ smbrdr_session_init(smb_ntdomain_t *di) (void) rw_unlock(&session->rwl); } - syslog(LOG_WARNING, "smbrdr: no session available"); - return (0); + syslog(LOG_DEBUG, "smbrdr: no session available"); + return (NULL); } /* @@ -550,10 +475,8 @@ smbrdr_session_disconnect(struct sdb_session *session, int cleanup) { int state; - if (session == 0) { - syslog(LOG_ERR, "smbrdr: (disconnect) null session"); + if (session == NULL) return; - } state = session->state; if ((state != SDB_SSTATE_DISCONNECTING) && @@ -567,7 +490,7 @@ smbrdr_session_disconnect(struct sdb_session *session, int cleanup) */ session->state = (state == SDB_SSTATE_STALE) ? SDB_SSTATE_CLEANING : SDB_SSTATE_DISCONNECTING; - (void) smbrdr_smb_logoff(&session->logon); + (void) smbrdr_logoffx(&session->logon); nb_close(session->sock); smbrdr_session_clear(session); } @@ -605,10 +528,8 @@ smbrdr_session_lock(char *server, char *username, int lmode) struct sdb_session *session; int i; - if (server == 0) { - syslog(LOG_ERR, "smbrdr: (lookup) no server specified"); - return (0); - } + if (server == NULL) + return (NULL); for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { session = &session_table[i]; @@ -624,7 +545,7 @@ smbrdr_session_lock(char *server, char *username, int lmode) return (session); (void) rw_unlock(&session->rwl); - return (0); + return (NULL); } return (session); } @@ -632,7 +553,7 @@ smbrdr_session_lock(char *server, char *username, int lmode) (void) rw_unlock(&session->rwl); } - return (0); + return (NULL); } /* @@ -649,13 +570,11 @@ mlsvc_session_native_values(int fid, int *remote_os, struct sdb_netuse *netuse; struct sdb_ofile *ofile; - if (remote_os == 0 || remote_lm == 0) { - syslog(LOG_ERR, "mlsvc_session_native_values: null"); + if (remote_os == NULL || remote_lm == NULL) return (-1); - } if ((ofile = smbrdr_ofile_get(fid)) == 0) { - syslog(LOG_ERR, + syslog(LOG_DEBUG, "mlsvc_session_native_values: unknown file (%d)", fid); return (-1); } @@ -672,96 +591,6 @@ mlsvc_session_native_values(int fid, int *remote_os, } /* - * smbrdr_disconnect_sessions - * - * Disconnects/cleanups all the sessions - */ -static void -smbrdr_disconnect_sessions(int cleanup) -{ - struct sdb_session *session; - int i; - - for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { - session = &session_table[i]; - (void) rw_wrlock(&session->rwl); - smbrdr_session_disconnect(&session_table[i], cleanup); - (void) rw_unlock(&session->rwl); - } -} - - -/* - * mlsvc_check_sessions - * - * This function should be run in an independent thread. At the time of - * writing it is called periodically from an infinite loop in the start - * up thread once initialization is complete. It sends a NetBIOS keep- - * alive message on each active session and handles cleanup if a session - * is closed from the remote end. Testing demonstrated that the domain - * controller will close a session after 15 minutes of inactivity. Note - * that neither NetBIOS keep-alive nor SMB echo is deemed as activity - * in this case, however, RPC requests appear to reset the timeout and - * keep the session open. Note that the NetBIOS request does stop the - * remote NetBIOS layer from timing out the connection. - */ -void -mlsvc_check_sessions(void) -{ - static int session_keep_alive; - struct sdb_session *session; - smb_ntdomain_t di; - int i; - - ++session_keep_alive; - - for (i = 0; i < MLSVC_DOMAIN_MAX; ++i) { - session = &session_table[i]; - - (void) rw_wrlock(&session->rwl); - - if (session->state < SDB_SSTATE_CONNECTED) { - (void) rw_unlock(&session->rwl); - continue; - } - - /* - * NetBIOS is only used on with port 139. The keep alive - * is not relevant over NetBIOS-less SMB over port 445. - * This is just to see if the socket is still alive. - */ - if (session->port == SSN_SRVC_TCP_PORT) { - if (nb_keep_alive(session->sock) != 0) { - session->state = SDB_SSTATE_STALE; - (void) rw_unlock(&session->rwl); - continue; - } - } - - if (session_keep_alive >= MLSVC_SESSION_FORCE_KEEPALIVE) { - if (smbrdr_smb_echo(session) != 0) { - syslog(LOG_WARNING, - "smbrdr: monitor[%s] cannot contact %s", - session->di.domain, session->di.server); - (void) memcpy(&di, &session->di, - sizeof (smb_ntdomain_t)); - session->state = SDB_SSTATE_STALE; - (void) rw_unlock(&session->rwl); - if (smb_getdomaininfo(0) == 0) - (void) smbrdr_locate_dc(di.domain); - } - } else - (void) rw_unlock(&session->rwl); - } - - if (session_keep_alive >= MLSVC_SESSION_FORCE_KEEPALIVE) { - session_keep_alive = 0; - /* cleanup */ - smbrdr_disconnect_sessions(1); - } -} - -/* * smbrdr_dump_sessions * * Debug function to dump the session table. @@ -812,7 +641,7 @@ mlsvc_echo(char *server) if ((session = smbrdr_session_lock(server, 0, SDB_SLCK_WRITE)) == 0) return (1); - if (smbrdr_smb_echo(session) != 0) { + if (smbrdr_echo(session) != 0) { session->state = SDB_SSTATE_STALE; res = -1; } @@ -822,7 +651,7 @@ mlsvc_echo(char *server) } /* - * smbrdr_smb_echo + * smbrdr_echo * * This request can be used to test the connection to the server. The * server should echo the data sent. The server should ignore the tid @@ -832,7 +661,7 @@ mlsvc_echo(char *server) * Return 0 on success. Otherwise return a -ve error code. */ static int -smbrdr_smb_echo(struct sdb_session *session) +smbrdr_echo(struct sdb_session *session) { static char *echo_str = "smbrdr"; smbrdr_handle_t srh; @@ -847,43 +676,21 @@ smbrdr_smb_echo(struct sdb_session *session) } status = smbrdr_request_init(&srh, SMB_COM_ECHO, session, 0, 0); - - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrEcho: %s", xlate_nt_status(status)); + if (status != NT_STATUS_SUCCESS) return (-1); - } rc = smb_msgbuf_encode(&srh.srh_mbuf, "bwws", 1, 1, strlen(echo_str), echo_str); if (rc <= 0) { - syslog(LOG_ERR, "SmbrdrEcho: encode failed"); smbrdr_handle_free(&srh); return (-1); } status = smbrdr_exchange(&srh, &smb_hdr, 10); - if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrEcho: %s", xlate_nt_status(status)); - rc = -1; - } else { - rc = 0; - } - smbrdr_handle_free(&srh); - return (rc); -} -/* - * smbrdr_locate_dc - * - * Locate a domain controller. Note that this may close an existing - * connection to the current domain controller. - */ -static int -smbrdr_locate_dc(char *domain) -{ - if (mlsvc_locate_pdc) - return (mlsvc_locate_pdc(domain)); + if (status != NT_STATUS_SUCCESS) + return (-1); return (0); } diff --git a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c index 24bf3a5cea..1fea4e831d 100644 --- a/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c +++ b/usr/src/lib/smbsrv/libsmbrdr/common/smbrdr_transact.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -33,7 +33,6 @@ #include <strings.h> #include <smbsrv/libsmbrdr.h> - #include <smbsrv/ntstatus.h> #include <smbsrv/smb.h> #include <smbrdr.h> @@ -54,13 +53,12 @@ static int decode_smb_transact(smb_msgbuf_t *, char *, unsigned, smb_transact_rsp_t *); /* - * smbrdr_rpc_transact + * smbrdr_transact * * Send a SMB_COM_TRANSACTION request. */ int -smbrdr_rpc_transact(int fid, char *out_buf, int out_len, - char *in_buf, int in_len) +smbrdr_transact(int fid, char *out_buf, int out_len, char *in_buf, int in_len) { struct sdb_session *session; struct sdb_netuse *netuse; @@ -86,7 +84,8 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, session, logon, netuse); if (status != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "SmbrdrTransact: %s", xlate_nt_status(status)); + syslog(LOG_DEBUG, "smbrdr_transact: %s", + xlate_nt_status(status)); smbrdr_ofile_put(ofile); return (-1); } @@ -96,8 +95,7 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, rc = prep_smb_transact(mb, ofile->fid, out_buf, out_len, in_len, session->remote_caps & CAP_UNICODE); if (rc < 0) { - syslog(LOG_ERR, - "smbrdr_rpc_transact: prep_smb_transact failed"); + syslog(LOG_DEBUG, "smbrdr_transact: prep failed"); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); return (rc); @@ -110,7 +108,7 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, smbrdr_unlock_transport(); smbrdr_handle_free(&srh); smbrdr_ofile_put(ofile); - syslog(LOG_ERR, "smbrdr_rpc_transact: send failed"); + syslog(LOG_DEBUG, "smbrdr_transact: send failed"); return (-1); } @@ -120,15 +118,15 @@ smbrdr_rpc_transact(int fid, char *out_buf, int out_len, do { if (smbrdr_rcv(&srh, first_rsp) != NT_STATUS_SUCCESS) { - syslog(LOG_ERR, "smbrdr_rpc_transact: nb_rcv failed"); + syslog(LOG_DEBUG, "smbrdr_transact: nb_rcv failed"); rc = -1; break; } rc = decode_smb_transact(mb, in_buf, cur_inlen, &rsp); if (rc < 0 || rsp.TotalDataCount > in_len) { - syslog(LOG_ERR, - "SmbTransact: transact decode failure!"); + syslog(LOG_DEBUG, + "smbrdr_transact: decode failed"); rc = -1; break; } @@ -222,7 +220,6 @@ decode_smb_transact(smb_msgbuf_t *mb, char *in, unsigned in_len, rc = smb_msgbuf_decode(mb, "b", &rsp->WordCount); if (rc <= 0 || rsp->WordCount < 10) { - syslog(LOG_ERR, "SmbTransact: invalid word count"); return (-1); } diff --git a/usr/src/pkgdefs/SUNWsmbsu/prototype_com b/usr/src/pkgdefs/SUNWsmbsu/prototype_com index ba9aa3d77d..c9963bdfd2 100644 --- a/usr/src/pkgdefs/SUNWsmbsu/prototype_com +++ b/usr/src/pkgdefs/SUNWsmbsu/prototype_com @@ -20,7 +20,7 @@ # # -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -64,6 +64,8 @@ d none usr/lib/mdb/kvm 755 root sys d none usr/lib/fs 755 root sys d none usr/lib/fs/smb 755 root sys f none usr/lib/fs/smb/libshare_smb.so.1 755 root bin +f none usr/lib/libsqlite.so.1 755 root bin +s none usr/lib/libsqlite.so=libsqlite.so.1 d none usr/lib/security 755 root bin f none usr/lib/security/pam_smb_passwd.so.1 755 root bin -s none usr/lib/security/pam_smb_passwd.so=./pam_smb_passwd.so.1 +s none usr/lib/security/pam_smb_passwd.so=pam_smb_passwd.so.1 diff --git a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c index d29e55eda6..9d6d0c202d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_check_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_check_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,7 +74,7 @@ smb_com_check_directory(struct smb_request *sr) struct smb_node *dnode; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -88,7 +88,7 @@ smb_com_check_directory(struct smb_request *sr) rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -104,7 +104,7 @@ smb_com_check_directory(struct smb_request *sr) smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_errno(sr, ENOTDIR); + smbsr_errno(sr, ENOTDIR); /* NOTREACHED */ } @@ -114,8 +114,7 @@ smb_com_check_directory(struct smb_request *sr) SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); if (rc != 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_close.c b/usr/src/uts/common/fs/smbsrv/smb_close.c index c4d129c2e4..f2d7faeb8d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb_close.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,14 +53,13 @@ smb_com_close(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } rc = smb_common_close(sr, last_wtime); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -86,8 +85,7 @@ smb_com_close_and_tree_disconnect(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -96,7 +94,7 @@ smb_com_close_and_tree_disconnect(struct smb_request *sr) smb_tree_disconnect(sr->tid_tree); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c index d3a462fbc5..5e0d94976b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -37,22 +37,10 @@ #include <smbsrv/ntstatus.h> #include <smbsrv/smbinfo.h> #include <sys/fcntl.h> +#include <sys/nbmlock.h> extern uint32_t smb_is_executable(char *path); -#define DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0) - -#define DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0) - -#define DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0) - -#define DENY_RW(share_access) \ - ((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0) - -#define DENY_ALL(share_access) (share_access == 0) - -#define DENY_NONE(share_access) (share_access == FILE_SHARE_ALL) - /* * The default stability mode is to perform the write-through * behaviour requested by the client. @@ -219,130 +207,6 @@ smb_ofun_to_crdisposition(uint16_t ofun) } /* - * smb_open_share_check - * - * check file sharing rules for current open request - * against the given existing open. - * - * Returns NT_STATUS_SHARING_VIOLATION if there is any - * sharing conflict, otherwise returns NT_STATUS_SUCCESS. - */ -uint32_t -smb_open_share_check(struct smb_request *sr, - struct smb_node *node, - struct smb_ofile *open) -{ - uint32_t desired_access; - uint32_t share_access; - - desired_access = sr->arg.open.desired_access; - share_access = sr->arg.open.share_access; - - /* - * As far as I can tell share modes are not relevant to - * directories. The check for exclusive access (Deny RW) - * remains because I don't know whether or not it was here - * for a reason. - */ - if (node->attr.sa_vattr.va_type == VDIR) { - if (DENY_RW(open->f_share_access) && - (node->n_orig_uid != crgetuid(sr->user_cr))) { - return (NT_STATUS_SHARING_VIOLATION); - } - - return (NT_STATUS_SUCCESS); - } - - /* if it's just meta data */ - if ((open->f_granted_access & FILE_DATA_ALL) == 0) - return (NT_STATUS_SUCCESS); - - /* - * Check requested share access against the - * open granted (desired) access - */ - if (DENY_DELETE(share_access) && (open->f_granted_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_READ(share_access) && - (open->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_WRITE(share_access) && - (open->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - /* check requested desired access against the open share access */ - if (DENY_DELETE(open->f_share_access) && (desired_access & DELETE)) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_READ(open->f_share_access) && - (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) - return (NT_STATUS_SHARING_VIOLATION); - - if (DENY_WRITE(open->f_share_access) && - (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (NT_STATUS_SHARING_VIOLATION); - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_file_share_check - * - * check file sharing rules for current open request - * against all existing opens for a file. - * - * Returns NT_STATUS_SHARING_VIOLATION if there is any - * sharing conflict, otherwise returns NT_STATUS_SUCCESS. - */ -uint32_t -smb_file_share_check(struct smb_request *sr, struct smb_node *node) -{ - struct smb_ofile *open; - uint32_t status; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - /* if it's just meta data */ - if ((sr->arg.open.desired_access & FILE_DATA_ALL) == 0) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - open = smb_llist_head(&node->n_ofile_list); - while (open) { - status = smb_open_share_check(sr, node, open); - if (status == NT_STATUS_SHARING_VIOLATION) { - smb_llist_exit(&node->n_ofile_list); - return (status); - } - open = smb_llist_next(&node->n_ofile_list, open); - } - smb_llist_exit(&node->n_ofile_list); - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_amask_to_amode - * Converts specific read/write access rights of access mask to access - * mode flags. - */ -int -smb_amask_to_amode(unsigned long amask) -{ - if ((amask & FILE_READ_DATA) && - (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA))) - return (O_RDWR); - - if (amask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) - return (O_WRONLY); - - return (O_RDONLY); -} - -/* * smb_open_subr * * Notes on write-through behaviour. It looks like pre-LM0.12 versions @@ -364,6 +228,7 @@ smb_amask_to_amode(unsigned long amask) * in which case it won't return to the caller. Be careful how you * handle things in here. */ + uint32_t smb_open_subr(struct smb_request *sr) { @@ -385,6 +250,8 @@ smb_open_subr(struct smb_request *sr) int is_stream; int lookup_flags = SMB_FOLLOW_LINKS; uint32_t daccess; + uint32_t share_access = op->share_access; + uint32_t uniq_fid; is_dir = (op->create_options & FILE_DIRECTORY_FILE) ? 1 : 0; @@ -397,7 +264,7 @@ smb_open_subr(struct smb_request *sr) if ((op->create_disposition != FILE_CREATE) && (op->create_disposition != FILE_OPEN_IF) && (op->create_disposition != FILE_OPEN)) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_ACCESS); /* invalid open mode */ /* NOTREACHED */ @@ -417,7 +284,7 @@ smb_open_subr(struct smb_request *sr) sr->uid_user->u_name, xlate_nt_status(NT_STATUS_TOO_MANY_OPENED_FILES)); - smbsr_raise_cifs_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, + smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES, ERRDOS, ERROR_TOO_MANY_OPEN_FILES); /* NOTREACHED */ } @@ -437,7 +304,7 @@ smb_open_subr(struct smb_request *sr) * raise an exception or return success here. */ if ((rc = smb_rpc_open(sr)) != 0) { - smbsr_raise_nt_error(sr, rc); + smbsr_error(sr, rc, 0, 0); /* NOTREACHED */ } else { return (NT_STATUS_SUCCESS); @@ -445,13 +312,13 @@ smb_open_subr(struct smb_request *sr) break; default: - smbsr_raise_error(sr, ERRSRV, ERRinvdevice); + smbsr_error(sr, 0, ERRSRV, ERRinvdevice); /* NOTREACHED */ break; } if ((pathlen = strlen(op->fqi.path)) >= MAXPATHLEN) { - smbsr_raise_error(sr, ERRSRV, ERRfilespecs); + smbsr_error(sr, 0, ERRSRV, ERRfilespecs); /* NOTREACHED */ } @@ -466,7 +333,7 @@ smb_open_subr(struct smb_request *sr) op->fqi.srch_attr = op->fqi.srch_attr; if ((status = smb_validate_object_name(op->fqi.path, is_dir)) != 0) { - smbsr_raise_cifs_error(sr, status, ERRDOS, ERROR_INVALID_NAME); + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } @@ -476,7 +343,7 @@ smb_open_subr(struct smb_request *sr) if (rc = smb_pathname_reduce(sr, sr->user_cr, op->fqi.path, sr->tid_tree->t_snode, cur_node, &op->fqi.dir_snode, op->fqi.last_comp)) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -508,26 +375,41 @@ smb_open_subr(struct smb_request *sr) } else { smb_node_release(op->fqi.dir_snode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + /* + * The uniq_fid is a CIFS-server-wide unique identifier for an ofile + * which is used to uniquely identify open instances for the + * VFS share reservation mechanism (accessed via smb_fsop_shrlock()). + */ + + uniq_fid = SMB_UNIQ_FID(); + if (op->fqi.last_comp_was_found) { node = op->fqi.last_snode; dnode = op->fqi.dir_snode; /* + * Enter critical region for share reservations. + * (See comments above smb_fsop_shrlock().) + */ + + rw_enter(&node->n_share_lock, RW_WRITER); + + /* * Reject this request if the target is a directory * and the client has specified that it must not be * a directory (required by Lotus Notes). */ if ((op->create_options & FILE_NON_DIRECTORY_FILE) && (op->fqi.last_attr.sa_vattr.va_type == VDIR)) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_FILE_IS_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -539,19 +421,20 @@ smb_open_subr(struct smb_request *sr) * Directories cannot be opened * with the above commands */ + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_FILE_IS_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_FILE_IS_A_DIRECTORY, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } } else if (op->my_flags & MYF_MUST_BE_DIRECTORY) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_NOT_A_DIRECTORY, + smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, ERRDOS, ERROR_DIRECTORY); /* NOTREACHED */ } @@ -561,10 +444,11 @@ smb_open_subr(struct smb_request *sr) * flag is set. */ if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_DELETE_PENDING, + smbsr_error(sr, NT_STATUS_DELETE_PENDING, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -573,12 +457,12 @@ smb_open_subr(struct smb_request *sr) * Specified file already exists so the operation should fail. */ if (op->create_disposition == FILE_CREATE) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, - ERROR_ALREADY_EXISTS); + smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, + ERRDOS, ERROR_ALREADY_EXISTS); /* NOTREACHED */ } @@ -591,18 +475,42 @@ smb_open_subr(struct smb_request *sr) if (node->attr.sa_vattr.va_type != VDIR) { if (op->desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA)) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_error(sr, ERRDOS, - ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); /* NOTREACHED */ } } } - status = smb_file_share_check(sr, node); + /* + * The following check removes the need to check share + * reservations again when a truncate is done. + */ + + if ((op->create_disposition == FILE_SUPERSEDE) || + (op->create_disposition == FILE_OVERWRITE_IF) || + (op->create_disposition == FILE_OVERWRITE)) { + + if (!(op->desired_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA))) { + rw_exit(&node->n_share_lock); + smb_node_release(node); + smb_node_release(dnode); + SMB_NULL_FQI_NODES(op->fqi); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); + } + } + + status = smb_fsop_shrlock(sr->user_cr, node, uniq_fid, + op->desired_access, share_access); + if (status == NT_STATUS_SHARING_VIOLATION) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); @@ -613,19 +521,19 @@ smb_open_subr(struct smb_request *sr) op->desired_access); if (status != NT_STATUS_SUCCESS) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); + if (status == NT_STATUS_PRIVILEGE_NOT_HELD) { - smbsr_raise_cifs_error(sr, - status, - ERRDOS, - ERROR_PRIVILEGE_NOT_HELD); + smbsr_error(sr, status, + ERRDOS, ERROR_PRIVILEGE_NOT_HELD); } else { - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, - ERRDOS, - ERROR_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); } } @@ -634,14 +542,16 @@ smb_open_subr(struct smb_request *sr) * has the file open, this will force a flush or close, * which may affect the outcome of any share checking. */ + if (OPLOCKS_IN_FORCE(node)) { status = smb_break_oplock(sr, node); if (status != NT_STATUS_SUCCESS) { + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, status, + smbsr_error(sr, status, ERRDOS, ERROR_VC_DISCONNECTED); /* NOTREACHED */ } @@ -652,29 +562,37 @@ smb_open_subr(struct smb_request *sr) case FILE_OVERWRITE_IF: case FILE_OVERWRITE: if (node->attr.sa_vattr.va_type == VDIR) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, - NT_STATUS_ACCESS_DENIED, ERRDOS, - ERROR_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } if (node->attr.sa_vattr.va_size != op->dsize) { node->flags &= ~NODE_FLAGS_SET_SIZE; + bzero(&new_attr, sizeof (new_attr)); new_attr.sa_vattr.va_size = op->dsize; new_attr.sa_mask = SMB_AT_SIZE; - if ((rc = smb_fsop_setattr(sr, sr->user_cr, - (&op->fqi)->last_snode, &new_attr, - &op->fqi.last_attr)) != 0) { + + rc = smb_fsop_setattr(sr, sr->user_cr, + node, &new_attr, &op->fqi.last_attr); + + if (rc) { + smb_fsop_unshrlock(sr->user_cr, + node, uniq_fid); + rw_exit(&node->n_share_lock); smb_node_release(node); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + op->dsize = op->fqi.last_attr.sa_vattr.va_size; } /* @@ -712,11 +630,10 @@ smb_open_subr(struct smb_request *sr) * fail with these two dispositions */ if (is_stream) - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_NOT_FOUND, + smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERROR_FILE_NOT_FOUND); else - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOTREACHED */ } @@ -731,32 +648,93 @@ smb_open_subr(struct smb_request *sr) new_attr.sa_vattr.va_type = VREG; new_attr.sa_vattr.va_mode = 0666; new_attr.sa_mask = SMB_AT_TYPE | SMB_AT_MODE; + + /* + * A problem with setting the readonly bit at + * create time is that this bit will prevent + * writes to the file from the same fid (which + * should be allowed). + * + * The solution is to set the bit at close time. + * Meanwhile, to prevent racing opens from being + * able to write to the file, the bit is set at + * create time until share reservations can be set + * to prevent write and delete access. At that point, + * the bit can be turned off until close (so as to + * allow writes from the same fid to the file). + */ + + if (op->dattr & SMB_FA_READONLY) { + new_attr.sa_dosattr = FILE_ATTRIBUTE_READONLY; + new_attr.sa_mask |= SMB_AT_DOSATTR; + } + rc = smb_fsop_create(sr, sr->user_cr, dnode, op->fqi.last_comp, &new_attr, &op->fqi.last_snode, &op->fqi.last_attr); + if (rc != 0) { smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + if (op->dattr & SMB_FA_READONLY) { + share_access &= ~(FILE_SHARE_WRITE | + FILE_SHARE_DELETE); + } + + node = op->fqi.last_snode; + + rw_enter(&node->n_share_lock, RW_WRITER); + + status = smb_fsop_shrlock(sr->user_cr, node, + uniq_fid, op->desired_access, + share_access); + + if (status == NT_STATUS_SHARING_VIOLATION) { + rw_exit(&node->n_share_lock); + smb_node_release(node); + smb_node_release(dnode); + SMB_NULL_FQI_NODES(op->fqi); + return (status); + } + + new_attr = op->fqi.last_attr; + new_attr.sa_mask = 0; + + if (op->dattr & SMB_FA_READONLY) { + new_attr.sa_dosattr &= ~FILE_ATTRIBUTE_READONLY; + new_attr.sa_mask |= SMB_AT_DOSATTR; + } + if (op->dsize) { new_attr.sa_vattr.va_size = op->dsize; - new_attr.sa_mask = SMB_AT_SIZE; - rc = smb_fsop_setattr(sr, sr->user_cr, - op->fqi.last_snode, &new_attr, - &op->fqi.last_attr); + new_attr.sa_mask |= SMB_AT_SIZE; + } + + if (new_attr.sa_mask) { + node->attr = new_attr; + node->what = new_attr.sa_mask; + rc = smb_sync_fsattr(sr, sr->user_cr, node); + if (rc != 0) { - smb_node_release(op->fqi.last_snode); + smb_fsop_unshrlock(sr->user_cr, node, + uniq_fid); + + rw_exit(&node->n_share_lock); + smb_node_release(node); (void) smb_fsop_remove(sr, sr->user_cr, dnode, op->fqi.last_comp, 0); smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ + } else { + op->fqi.last_attr = node->attr; } } @@ -772,30 +750,33 @@ smb_open_subr(struct smb_request *sr) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } + + node = op->fqi.last_snode; + rw_enter(&node->n_share_lock, RW_WRITER); } created = 1; op->action_taken = SMB_OACT_CREATED; } - if (node == 0) { - node = op->fqi.last_snode; - } - if ((op->fqi.last_attr.sa_vattr.va_type != VREG) && (op->fqi.last_attr.sa_vattr.va_type != VDIR) && (op->fqi.last_attr.sa_vattr.va_type != VLNK)) { /* not allowed to do this */ + + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + SMB_DEL_NEWOBJ(op->fqi); + rw_exit(&node->n_share_lock); smb_node_release(node); if (created) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -811,17 +792,20 @@ smb_open_subr(struct smb_request *sr) */ of = smb_ofile_open(sr->tid_tree, node, sr->smb_pid, op->desired_access, - op->create_options, op->share_access, SMB_FTYPE_DISK, NULL, 0, - &err); + op->create_options, share_access, SMB_FTYPE_DISK, NULL, 0, + uniq_fid, &err); if (of == NULL) { + smb_fsop_unshrlock(sr->user_cr, node, uniq_fid); + SMB_DEL_NEWOBJ(op->fqi); + rw_exit(&node->n_share_lock); smb_node_release(node); if (created) smb_rwx_rwexit(&dnode->n_lock); smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, err.status, err.errcls, err.errcode); + smbsr_error(sr, err.status, err.errcls, err.errcode); /* NOTREACHED */ } @@ -847,14 +831,20 @@ smb_open_subr(struct smb_request *sr) op->my_flags &= ~MYF_OPLOCK_MASK; if (status != NT_STATUS_SUCCESS) { + rw_exit(&node->n_share_lock); + /* + * smb_fsop_unshrlock() and smb_fsop_close() + * are called from smb_ofile_close() + */ (void) smb_ofile_close(of, 0); smb_ofile_release(of); if (created) smb_rwx_rwexit(&dnode->n_lock); + smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); - smbsr_raise_cifs_error(sr, status, + smbsr_error(sr, status, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ } @@ -868,11 +858,15 @@ smb_open_subr(struct smb_request *sr) /* * Clients may set the DOS readonly bit on create but they * expect subsequent write operations on the open fid to - * succeed. Thus the DOS readonly bit is not set until the - * file is closed. The NODE_CREATED_READONLY flag will - * inhibit other attempts to open the file with write access - * and act as the indicator to set the DOS readonly bit on + * succeed. Thus the DOS readonly bit is not set permanently + * until the file is closed. The NODE_CREATED_READONLY flag + * will act as the indicator to set the DOS readonly bit on * close. + * Above, the readonly bit is set on create, share + * reservations are set, and then the bit is unset. + * These actions allow writes to the open fid to succeed + * until the file is closed while preventing write access + * from other opens while this fid is active. */ if (op->dattr & SMB_FA_READONLY) { node->flags |= NODE_CREATED_READONLY; @@ -913,9 +907,11 @@ smb_open_subr(struct smb_request *sr) sr->smb_fid = of->f_fid; sr->fid_ofile = of; - if (created) { + rw_exit(&node->n_share_lock); + + if (created) smb_rwx_rwexit(&dnode->n_lock); - } + smb_node_release(dnode); SMB_NULL_FQI_NODES(op->fqi); diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_search.c b/usr/src/uts/common/fs/smbsrv/smb_common_search.c index a17555669b..84d35fe9b0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_search.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -41,7 +41,6 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) smb_odir_t *od; smb_node_t *node; char *last_component; - smb_session_t *session = sr->session; unsigned int rc; int erc; @@ -51,14 +50,14 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &node, last_component)) != 0) { kmem_free(last_component, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if ((node->vp)->v_type != VDIR) { smb_node_release(node); kmem_free(last_component, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRbadpath); + smbsr_error(sr, 0, ERRDOS, ERRbadpath); /* NOTREACHED */ } @@ -67,18 +66,11 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) smb_node_release(node); kmem_free(last_component, MAXNAMELEN); if (sr->smb_com == SMB_COM_SEARCH) { - if (session->capabilities & CAP_STATUS32) { - smbsr_setup_nt_status(sr, - ERROR_SEVERITY_WARNING, - NT_STATUS_NO_MORE_FILES); - return (SDRC_NORMAL_REPLY); - } else { - smbsr_raise_error(sr, - ERRDOS, ERROR_NO_MORE_FILES); - /* NOTREACHED */ - } + smbsr_warn(sr, NT_STATUS_NO_MORE_FILES, + ERRDOS, ERROR_NO_MORE_FILES); + return (SDRC_NORMAL_REPLY); } else { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -89,7 +81,7 @@ smb_rdir_open(smb_request_t *sr, char *path, unsigned short sattr) kmem_free(last_component, sizeof (od->d_pattern)); if (od == NULL) { smb_node_release(node); - smbsr_raise_error(sr, ERRDOS, ERROR_NO_MORE_FILES); + smbsr_error(sr, 0, ERRDOS, ERROR_NO_MORE_FILES); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c index 2558716c5e..dff0a689dd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ @@ -89,7 +89,7 @@ smb_com_transaction(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == NULL) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -114,17 +114,17 @@ smb_com_transaction(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, suwcnt * 2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -132,7 +132,7 @@ smb_com_transaction(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -144,7 +144,7 @@ smb_com_transaction(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -161,13 +161,13 @@ smb_com_transaction_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -194,13 +194,13 @@ smb_com_transaction_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -266,7 +266,7 @@ smb_com_transaction2(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt, msrcnt, suwcnt); if (xa == 0) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -278,17 +278,17 @@ smb_com_transaction2(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, suwcnt*2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -296,7 +296,7 @@ smb_com_transaction2(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -308,7 +308,7 @@ smb_com_transaction2(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -325,13 +325,13 @@ smb_com_transaction2_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -359,13 +359,13 @@ smb_com_transaction2_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -418,15 +418,15 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case NT_TRANSACT_QUERY_QUOTA: (void) smb_nt_transact_query_quota(sr, xa); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ case NT_TRANSACT_SET_QUOTA: - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ default: - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ } @@ -441,7 +441,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case SDRC_UNIMPLEMENTED: case SDRC_UNSUPPORTED: - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ default: @@ -455,7 +455,7 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) if (xa->smb_msrcnt < n_setup || xa->smb_mprcnt < n_param || xa->smb_mdrcnt < n_data) { - smbsr_raise_error(sr, ERRSRV, ERRsmbcmd); + smbsr_error(sr, 0, ERRSRV, ERRsmbcmd); /* NOTREACHED */ } @@ -539,7 +539,7 @@ smb_com_nt_transact(struct smb_request *sr) xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount, MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount); if (xa == 0) { - smbsr_raise_error(sr, ERRSRV, ERRnoroom); + smbsr_error(sr, 0, ERRSRV, ERRnoroom); /* NOTREACHED */ } @@ -552,17 +552,17 @@ smb_com_nt_transact(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv, sr->smb_vwv.chain_offset, SetupCount * 2)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -570,7 +570,7 @@ smb_com_nt_transact(struct smb_request *sr) if (smb_xa_open(xa)) { smb_xa_rele(sr->session, xa); - smbsr_raise_error(sr, ERRDOS, ERRsrverror); + smbsr_error(sr, 0, ERRDOS, ERRsrverror); /* NOTREACHED */ } sr->r_xa = xa; @@ -582,7 +582,7 @@ smb_com_nt_transact(struct smb_request *sr) if (!smb_xa_complete(xa)) { smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } @@ -599,13 +599,13 @@ smb_com_nt_transact_secondary(struct smb_request *sr) int rc; if ((xa = smbsr_lookup_xa(sr)) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRsrverror); + smbsr_error(sr, 0, ERRSRV, ERRsrverror); /* NOTREACHED */ } if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -633,13 +633,13 @@ smb_com_nt_transact_secondary(struct smb_request *sr) if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) { mutex_exit(&xa->xa_mutex); smb_xa_close(xa); - smbsr_raise_error(sr, ERRDOS, ERRbadformat); + smbsr_error(sr, 0, ERRDOS, ERRbadformat); /* NOTREACHED */ } mutex_exit(&xa->xa_mutex); @@ -1926,8 +1926,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -1942,7 +1941,7 @@ smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) case TRANS_WAIT_NMPIPE: if (is_supported_pipe(xa->xa_smb_trans_name) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOT REACHED */ } rc = SDRC_NORMAL_REPLY; @@ -2120,8 +2119,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2134,8 +2132,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2148,8 +2145,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2162,8 +2158,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } @@ -2176,8 +2171,7 @@ smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa) * data back to client. */ if (n_data == 0) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INFO_LENGTH_MISMATCH, + smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH, ERRDOS, ERROR_BAD_LENGTH); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c index 7906233a35..6947474f77 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_tree.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_tree.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,7 @@ smbsr_connect_tree(struct smb_request *sr) char *sharename; char *access_msg; int32_t stype; + DWORD status; int rc; errmsg[0] = '\0'; @@ -77,12 +78,12 @@ smbsr_connect_tree(struct smb_request *sr) * Looks like a UNC path, make sure the format is correct. */ if (sharename[1] != '\\') { - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } if ((sharename = strchr(sharename+2, '\\')) == 0) { - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } @@ -91,12 +92,12 @@ smbsr_connect_tree(struct smb_request *sr) /* * This should be a sharename: no embedded '\' allowed. */ - smbsr_raise_error(sr, ERRSRV, ERRinvnetname); + smbsr_error(sr, 0, ERRSRV, ERRinvnetname); /* NOTREACHED */ } if (smb_get_stype(sharename, sr->arg.tcon.service, &stype) != 0) { - smbsr_raise_cifs_error(sr, NT_STATUS_BAD_DEVICE_TYPE, + smbsr_error(sr, NT_STATUS_BAD_DEVICE_TYPE, ERRDOS, ERROR_BAD_DEV_TYPE); /* NOTREACHED */ } @@ -106,14 +107,11 @@ smbsr_connect_tree(struct smb_request *sr) smbsr_share_report(sr, sharename, access_msg, errmsg); /* - * W2K sometimes tries to connect to user shares using an - * anonymous IPC connection. NT returns access denied. + * Windows 2000 may try to connect to user shares using + * an anonymous IPC connection. NT returns access denied. */ - if (rc == ERRaccess) - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, - ERRSRV, ERRaccess); - else - smbsr_raise_error(sr, ERRSRV, rc); + status = (rc == ERRaccess) ? NT_STATUS_ACCESS_DENIED : 0; + smbsr_error(sr, status, ERRSRV, rc); /* NOTREACHED */ } @@ -167,11 +165,11 @@ smbsr_share_report(struct smb_request *sr, char *sharename, /* * smbsr_setup_share * - * This is where the real of setting up share is done. The main thing - * to note is that we resolve ambiguities by assuming that a directory is - * being requested. This function returns error codes, rather than calling - * smbsr_raise_error. We return 0 on success or a non-zero error code if - * there is a problem. + * This is where the real of setting up share is done. + * Note that ambiguities are resolved by assuming that a directory + * is being requested. + * + * Returns 0 on success or a non-zero error code on failure. */ int smbsr_setup_share(struct smb_request *sr, char *sharename, int32_t stype, diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c index 8fd289bb75..c38bbfd819 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,13 +62,13 @@ smb_com_create(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -107,13 +107,13 @@ smb_com_create_new(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -165,13 +165,13 @@ smb_com_create_temporary(struct smb_request *sr) break; case NT_STATUS_SHARING_VIOLATION: - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ break; default: - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ break; } @@ -198,7 +198,7 @@ smb_common_create(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c index e369f59b47..cb6e3f6e72 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,11 +93,7 @@ smb_com_create_directory(struct smb_request *sr) } if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_NAME); - + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } @@ -110,12 +106,12 @@ smb_com_create_directory(struct smb_request *sr) while (smbpath_next(spp)) { rc = smb_common_create_directory(sr); if (rc != 0 && rc != EEXIST) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); } /* We should have created one directory successfully! */ if (rc != 0) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); smbsr_encode_empty_result(sr); return (SDRC_NORMAL_REPLY); @@ -164,7 +160,7 @@ smb_common_create_directory(struct smb_request *sr) struct smb_node *node; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c index f35e3c4273..c3a4dad862 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,10 +28,10 @@ #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smbinfo.h> +#include <sys/nbmlock.h> -static DWORD smb_delete_check(struct smb_request *sr, struct smb_node *node, - uint16_t dattr, smb_error_t *smberr); -static DWORD smb_delete_share_check(struct smb_node *node); +static uint32_t smb_delete_check(smb_request_t *sr, smb_node_t *node, + smb_error_t *smberr); /* * smb_com_delete @@ -104,32 +104,22 @@ smb_com_delete(struct smb_request *sr) int is_stream; smb_odir_context_t *pc; - pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); - fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); - sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); - name = kmem_alloc(MAXNAMELEN, KM_SLEEP); - fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); - if (smbsr_decode_vwv(sr, "w", &sattr) != 0) { - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); smbsr_decode_error(sr); /* NOTREACHED */ } if (smbsr_decode_data(sr, "%S", sr, &path) != 0) { - kmem_free(pc, sizeof (*pc)); - kmem_free(name, MAXNAMELEN); - kmem_free(fname, MAXNAMELEN); - kmem_free(sname, MAXNAMELEN); - kmem_free(fullname, MAXPATHLEN); smbsr_decode_error(sr); /* NOTREACHED */ } + pc = kmem_zalloc(sizeof (*pc), KM_SLEEP); + fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); + sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); + name = kmem_alloc(MAXNAMELEN, KM_SLEEP); + fullname = kmem_alloc(MAXPATHLEN, KM_SLEEP); + is_stream = smb_stream_parse_name(path, fname, sname); (void) smb_rdir_open(sr, path, sattr); @@ -145,14 +135,50 @@ smb_com_delete(struct smb_request *sr) while ((rc = smb_rdir_next(sr, &node, pc)) == 0) { (void) strlcpy(name, pc->dc_name, MAXNAMELEN); - if (smb_delete_check(sr, node, pc->dc_dattr, &smberr) - != NT_STATUS_SUCCESS) { + if (pc->dc_dattr & SMB_FA_DIRECTORY) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_ACCESS_DENIED; + smberr.status = NT_STATUS_FILE_IS_A_DIRECTORY; smb_node_release(node); goto delete_error; } - smb_node_release(node); - node = NULL; + if ((pc->dc_dattr & SMB_FA_READONLY) || + (node->flags & NODE_CREATED_READONLY)) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_ACCESS_DENIED; + smberr.status = NT_STATUS_CANNOT_DELETE; + smb_node_release(node); + goto delete_error; + } + + /* + * NT does not always close a file immediately, which + * can cause the share and access checking to fail + * (the node refcnt is greater than one), and the file + * doesn't get deleted. Breaking the oplock before + * share and access checking gives the client a chance + * to close the file. + */ + + if (OPLOCKS_IN_FORCE(node)) { + smberr.status = smb_break_oplock(sr, node); + + if (smberr.status != NT_STATUS_SUCCESS) { + smberr.errcls = ERRDOS; + smberr.errcode = ERROR_VC_DISCONNECTED; + smb_node_release(node); + goto delete_error; + } + } + + smb_node_start_crit(node, RW_READER); + + if (smb_delete_check(sr, node, &smberr)) { + smb_node_end_crit(node); + smb_node_release(node); + goto delete_error; + } if (is_stream) { /* @@ -177,6 +203,10 @@ smb_com_delete(struct smb_request *sr) name, od); } + smb_node_end_crit(node); + smb_node_release(node); + node = NULL; + if (rc != 0) { if (rc != ENOENT) { smb_rdir_close(sr); @@ -185,7 +215,7 @@ smb_com_delete(struct smb_request *sr) kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } } else { @@ -201,7 +231,7 @@ smb_com_delete(struct smb_request *sr) kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -231,57 +261,20 @@ delete_error: kmem_free(fname, MAXNAMELEN); kmem_free(sname, MAXNAMELEN); kmem_free(fullname, MAXPATHLEN); - smbsr_raise_cifs_error(sr, - smberr.status, smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ return (SDRC_NORMAL_REPLY); /* compiler complains otherwise */ } -static DWORD -smb_delete_check( - struct smb_request *sr, - struct smb_node *node, - uint16_t dattr, - smb_error_t *smberr) +uint32_t +smb_delete_check(smb_request_t *sr, smb_node_t *node, smb_error_t *smberr) { - if (dattr & SMB_FA_DIRECTORY) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_ACCESS_DENIED; - smberr->status = NT_STATUS_FILE_IS_A_DIRECTORY; - return (NT_STATUS_UNSUCCESSFUL); - } - - if ((dattr & SMB_FA_READONLY) || - (node->flags & NODE_CREATED_READONLY)) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_ACCESS_DENIED; - smberr->status = NT_STATUS_CANNOT_DELETE; - return (NT_STATUS_UNSUCCESSFUL); - } - - /* - * NT does not always close a file immediately, which - * can cause the share and access checking to fail - * (the node refcnt is greater than one), and the file - * doesn't get deleted. Breaking the oplock before - * share and access checking gives the client a chance - * to close the file. - */ - if (OPLOCKS_IN_FORCE(node)) { - smberr->status = smb_break_oplock(sr, node); + smberr->status = smb_node_delete_check(node); - if (smberr->status != NT_STATUS_SUCCESS) { - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_VC_DISCONNECTED; - return (NT_STATUS_UNSUCCESSFUL); - } - } - - smberr->status = smb_delete_share_check(node); if (smberr->status == NT_STATUS_SHARING_VIOLATION) { smberr->errcls = ERRDOS; smberr->errcode = ERROR_SHARING_VIOLATION; - return (NT_STATUS_UNSUCCESSFUL); + return (smberr->status); } /* @@ -294,61 +287,15 @@ smb_delete_check( * W2K rejects lock requests on open files which are opened * with Metadata open modes. The error is STATUS_ACCESS_DENIED. */ - if (smb_lock_range_access(sr, node, 0, 0, FILE_WRITE_DATA) != - NT_STATUS_SUCCESS) { + + smberr->status = smb_range_check(sr, sr->user_cr, node, 0, + UINT64_MAX, B_TRUE); + + if (smberr->status != NT_STATUS_SUCCESS) { smberr->errcls = ERRDOS; smberr->errcode = ERROR_ACCESS_DENIED; smberr->status = NT_STATUS_ACCESS_DENIED; - return (NT_STATUS_UNSUCCESSFUL); } - - return (NT_STATUS_SUCCESS); -} - -/* - * smb_delete_share_check - * - * An open file can be deleted only if opened for - * accessing meta data. Share modes aren't important - * in this case. - * - * NOTE: there is another mechanism for deleting an - * open file that NT clients usually use this method. - * That's setting "Delete on close" flag for an open - * file, in this way the file will be deleted after - * last close. This flag can be set by SmbTrans2SetFileInfo - * with FILE_DISPOSITION_INFO information level. - * For setting this flag file should be opened by - * DELETE access in the FID that is passed in the Trans2 - * request. - */ -static DWORD -smb_delete_share_check(struct smb_node *node) -{ - smb_ofile_t *file; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - if (node->attr.sa_vattr.va_type == VDIR) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - file = smb_llist_head(&node->n_ofile_list); - while (file) { - ASSERT(file->f_magic == SMB_OFILE_MAGIC); - if (file->f_granted_access & - (FILE_READ_DATA | - FILE_WRITE_DATA | - FILE_APPEND_DATA | - FILE_EXECUTE | - DELETE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - file = smb_llist_next(&node->n_ofile_list, file); - } - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SUCCESS); + return (smberr->status); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c index e959b240b8..514551ad97 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -63,7 +63,7 @@ smb_com_delete_directory(struct smb_request *sr) int rc; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -77,7 +77,7 @@ smb_com_delete_directory(struct smb_request *sr) rc = smbd_fs_query(sr, &sr->arg.dirop.fqi, FQM_PATH_MUST_EXIST); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -88,7 +88,7 @@ smb_com_delete_directory(struct smb_request *sr) smb_node_release(sr->arg.dirop.fqi.dir_snode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_cifs_error(sr, NT_STATUS_CANNOT_DELETE, + smbsr_error(sr, NT_STATUS_CANNOT_DELETE, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -102,7 +102,7 @@ smb_com_delete_directory(struct smb_request *sr) if (rc != 0) { smb_node_release(dnode); SMB_NULL_FQI_NODES(sr->arg.dirop.fqi); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c index 96a23bb995..0cc54ae43e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * @@ -145,7 +145,6 @@ #define SMB_ALL_DISPATCH_STAT_INCR(stat) atomic_inc_64(&stat); -int smb_dispatch_diags = 0; static kstat_t *smb_dispatch_ksp = NULL; static kstat_named_t *smb_dispatch_kstat_data = NULL; static int smb_dispatch_kstat_size = 0; @@ -773,6 +772,7 @@ smb_dispatch_request(struct smb_request *sr) { int rc; smb_dispatch_table_t *sdd; + smb_error_t err; ASSERT(sr->tid_tree == 0); ASSERT(sr->uid_user == 0); @@ -834,20 +834,16 @@ smb_dispatch_request(struct smb_request *sr) sr->first_smb_com = sr->smb_com; /* - * Verify SMB signature if signing is enabled, - * dialiect is NT LM 0.12, + * Verify SMB signature if signing is enabled, dialect is NT LM 0.12, * signing was negotiated and authentication has occurred. */ if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { if (smb_sign_check_request(sr) != 0) { - /* Reply with ACCESS_DENIED */ - if (sr->session->capabilities & CAP_STATUS32) - smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, - NT_STATUS_ACCESS_DENIED); - else { - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRnoaccess; - } + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_ACCESS_DENIED; + err.errcls = ERRDOS; + err.errcode = ERROR_ACCESS_DENIED; + smbsr_set_error(sr, &err); rc = -1; smb_rwx_rwenter(&sr->session->s_lock, RW_READER); goto reply_error; @@ -956,15 +952,14 @@ andx_more: sr->uid_user = smb_user_lookup_by_uid(sr->session, &sr->user_cr, sr->smb_uid); if (sr->uid_user == NULL) { - smbsr_raise_error(sr, ERRSRV, ERRbaduid); + smbsr_error(sr, 0, ERRSRV, ERRbaduid); /* NOTREACHED */ } if (!(sdd->sdt_flags & SDDF_SUPPRESS_TID)) { sr->tid_tree = smb_tree_lookup_by_tid( sr->uid_user, sr->smb_tid); if (sr->tid_tree == NULL) { - smbsr_raise_error(sr, ERRSRV, - ERRinvnid); + smbsr_error(sr, 0, ERRSRV, ERRinvnid); /* NOTREACHED */ } } @@ -1274,78 +1269,15 @@ smbsr_encode_empty_result(struct smb_request *sr) } /* - * cifs_raise_error - * - * Temporary workaround to the NT status versus Win32/SMB error codes - * decision: just report them both here. - */ -void -smbsr_raise_cifs_error(struct smb_request *sr, - DWORD status, - int error_class, - int error_code) -{ - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, error_class, error_code); - - /* NOTREACHED */ -} - -void -smbsr_raise_error(struct smb_request *sr, int errcls, int errcod) -{ - sr->smb_rcls = (unsigned char)errcls; - sr->smb_err = (uint16_t)errcod; - longjmp(&sr->exjb); -} - -/* - * smbsr_setup_nt_status - * - * Set up an NT status in the smb_request but don't long jump or try - * to do any error handling. There are times when we need a status set - * up in the response to indicate that the request has either failed - * or, at least, is only partially complete (possibly indicated by the - * severity) but we also need to return some information to the client. - */ -void -smbsr_setup_nt_status(struct smb_request *sr, - uint32_t severity, - uint32_t nt_status) -{ - nt_status |= severity; - sr->smb_rcls = nt_status & 0xff; - sr->smb_reh = (nt_status >> 8) & 0xff; - sr->smb_err = nt_status >> 16; - sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; -} - -void -smbsr_raise_nt_error(struct smb_request *sr, uint32_t errcod) -{ - errcod |= 0xc0000000; - sr->smb_rcls = errcod & 0xff; - sr->smb_reh = (errcod >> 8) & 0xff; - sr->smb_err = errcod >> 16; - sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; - longjmp(&sr->exjb); -} - - -/* - * Attempt to map errno values to SMB and NT status values. - * Note: ESRCH is used as special case to handle a lookup - * failure on streams. + * Map errno values to SMB and NT status values. + * Note: ESRCH is a special case to handle a streams lookup failure. */ static struct { - int unix_errno; - int smb_error_class; - int smb_error_value; - DWORD nt_status; -} -smb_errno_map[] = { + int errnum; + int errcls; + int errcode; + DWORD status32; +} smb_errno_map[] = { { ENOSPC, ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL }, { EDQUOT, ERRDOS, ERROR_DISK_FULL, NT_STATUS_DISK_FULL }, { EPERM, ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED }, @@ -1375,74 +1307,115 @@ smb_errno_map[] = { }; void -smb_errmap_unix2smb(int en, smb_error_t *smberr) +smbsr_map_errno(int errnum, smb_error_t *err) { int i; - smberr->status = NT_STATUS_UNSUCCESSFUL; - smberr->errcls = ERRDOS; - smberr->errcode = ERROR_GEN_FAILURE; - for (i = 0; i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); ++i) { - if (smb_errno_map[i].unix_errno == en) { - smberr->status = smb_errno_map[i].nt_status; - smberr->errcls = smb_errno_map[i].smb_error_class; - smberr->errcode = smb_errno_map[i].smb_error_value; + if (smb_errno_map[i].errnum == errnum) { + err->severity = ERROR_SEVERITY_ERROR; + err->status = smb_errno_map[i].status32; + err->errcls = smb_errno_map[i].errcls; + err->errcode = smb_errno_map[i].errcode; return; } } + + err->severity = ERROR_SEVERITY_ERROR; + err->status = NT_STATUS_INTERNAL_ERROR; + err->errcls = ERRDOS; + err->errcode = ERROR_INTERNAL_ERROR; } -int -smbsr_set_errno(struct smb_request *sr, int en) +void +smbsr_errno(struct smb_request *sr, int errnum) { - int i; + smb_error_t err; - ASSERT(en != -1); + smbsr_map_errno(errnum, &err); + smbsr_set_error(sr, &err); + longjmp(&sr->exjb); + /* NOTREACHED */ +} - /* - * If the client supports 32-bit NT status values, check for - * an appropriate mapping and raise an NT error, control won't - * return here due to the longjmp in smbsr_raise_nt_error. - */ - if (sr->session->capabilities & CAP_STATUS32) { - for (i = 0; - i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); - ++i) { - if (smb_errno_map[i].unix_errno == en) { - smbsr_raise_nt_error(sr, - smb_errno_map[i].nt_status); - /* NOTREACHED */ - } - } - } else { - for (i = 0; - i < sizeof (smb_errno_map)/sizeof (smb_errno_map[0]); - ++i) { - if (smb_errno_map[i].unix_errno == en) { - sr->smb_rcls = smb_errno_map[i].smb_error_class; - sr->smb_err = smb_errno_map[i].smb_error_value; - return (0); - } - } - } +/* + * Report a request processing warning. + */ +void +smbsr_warn(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) +{ + smb_error_t err; + + err.severity = ERROR_SEVERITY_WARNING; + err.status = status; + err.errcls = errcls; + err.errcode = errcode; - sr->smb_rcls = ERRSRV; - sr->smb_err = ERRerror; - return (-1); + smbsr_set_error(sr, &err); } +/* + * Report a request processing error. This function will not return. + */ void -smbsr_raise_errno(struct smb_request *sr, int en) +smbsr_error(smb_request_t *sr, DWORD status, uint16_t errcls, uint16_t errcode) { - if (smbsr_set_errno(sr, en) != 0) { - if (smb_dispatch_diags) { - cmn_err(CE_NOTE, "SmbErrno: errno=%d", en); - } - } + smb_error_t err; + err.severity = ERROR_SEVERITY_ERROR; + err.status = status; + err.errcls = errcls; + err.errcode = errcode; + + smbsr_set_error(sr, &err); longjmp(&sr->exjb); - /* no return */ + /* NOTREACHED */ +} + +/* + * Setup a request processing error. This function can be used to + * report 32-bit status codes or DOS errors. Set the status code + * to 0 (NT_STATUS_SUCCESS) to explicitly report a DOS error, + * regardless of the client capabilities. + * + * If status is non-zero and the client supports 32-bit status + * codes, report the status. Otherwise, report the DOS error. + */ +void +smbsr_set_error(smb_request_t *sr, smb_error_t *err) +{ + uint32_t status; + uint32_t severity; + uint32_t capabilities; + + ASSERT(sr); + ASSERT(err); + + status = err->status; + severity = (err->severity == 0) ? ERROR_SEVERITY_ERROR : err->severity; + capabilities = sr->session->capabilities; + + if ((err->errcls == 0) && (err->errcode == 0)) { + capabilities |= CAP_STATUS32; + if (status == 0) + status = NT_STATUS_INTERNAL_ERROR; + } + + if ((capabilities & CAP_STATUS32) && (status != 0)) { + status |= severity; + sr->smb_rcls = status & 0xff; + sr->smb_reh = (status >> 8) & 0xff; + sr->smb_err = status >> 16; + sr->smb_flg2 |= SMB_FLAGS2_NT_STATUS; + } else { + if ((err->errcls == 0) || (err->errcode == 0)) { + sr->smb_rcls = ERRSRV; + sr->smb_err = ERRerror; + } else { + sr->smb_rcls = (uint8_t)err->errcls; + sr->smb_err = (uint16_t)err->errcode; + } + } } smb_xa_t * diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c index 1492219714..a45e5cab64 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -248,7 +248,7 @@ smb_com_find(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -286,13 +286,13 @@ smb_com_find(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ smb_rdir_close(sr); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { smb_rdir_close(sr); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } @@ -408,7 +408,7 @@ smb_com_find_close(struct smb_request *sr) } if (key_len == 0) { /* begin search */ - smbsr_raise_error(sr, ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -423,7 +423,7 @@ smb_com_find_close(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c index 59f9ba12b2..f9686297f0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find_unique.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find_unique.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -264,13 +264,13 @@ smb_com_find_unique(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { kmem_free(vdb, sizeof (struct vardata_block)); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_flush.c b/usr/src/uts/common/fs/smbsrv/smb_flush.c index b9cfb8c349..c3da4a2352 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_flush.c +++ b/usr/src/uts/common/fs/smbsrv/smb_flush.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -93,7 +93,7 @@ smb_com_flush(smb_request_t *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c index 3d7292961e..561f640fd1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c @@ -19,26 +19,31 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <sys/sid.h> +#include <sys/nbmlock.h> #include <smbsrv/smb_fsops.h> #include <smbsrv/smb_kproto.h> #include <smbsrv/smbvar.h> #include <smbsrv/ntstatus.h> #include <smbsrv/ntaccess.h> +#include <smbsrv/smb_incl.h> #include <acl/acl_common.h> - -u_longlong_t smb_caller_id; +#include <sys/fcntl.h> +#include <sys/flock.h> +#include <fs/fs_subr.h> static int smb_fsop_amask_to_omode(uint32_t granted_access); static int smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd); +static callb_cpr_t *smb_fsop_frlock_callback(flk_cb_when_t when, void *error); + /* * The smb_fsop_* functions have knowledge of CIFS semantics. * @@ -65,7 +70,8 @@ smb_fsop_start() { int error; - smb_caller_id = fs_new_caller_id(); + smb_vop_start(); + error = smb_node_root_init(); if (error == 0) @@ -85,32 +91,26 @@ smb_fsop_stop() int smb_fsop_open(smb_ofile_t *of) { - caller_context_t ct; int mode; mode = smb_fsop_amask_to_omode(of->f_granted_access); - smb_get_caller_context(NULL, &ct); - /* * Assuming that same vnode is returned as we had before * (i.e. no special vnodes) */ - return (smb_vop_open(&of->f_node->vp, mode, of->f_cr, &ct)); + return (smb_vop_open(&of->f_node->vp, mode, of->f_cr)); } int smb_fsop_close(smb_ofile_t *of) { - caller_context_t ct; int mode; mode = smb_fsop_amask_to_omode(of->f_granted_access); - smb_get_caller_context(NULL, &ct); - - return (smb_vop_close(of->f_node->vp, mode, of->f_cr, &ct)); + return (smb_vop_close(of->f_node->vp, mode, of->f_cr)); } static int @@ -141,7 +141,6 @@ smb_fsop_create_with_sd( smb_attr_t *ret_attr, smb_fssd_t *fs_sd) { - caller_context_t ct; vsecattr_t *vsap; vsecattr_t vsecattr; acl_t *acl, *dacl, *sacl; @@ -159,7 +158,6 @@ smb_fsop_create_with_sd( flags = SMB_IGNORE_CASE; ASSERT(cr); - smb_get_caller_context(sr, &ct); is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0); @@ -191,10 +189,10 @@ smb_fsop_create_with_sd( if (is_dir) { rc = smb_vop_mkdir(snode->vp, name, attr, &vp, flags, - cr, &ct, vsap); + cr, vsap); } else { rc = smb_vop_create(snode->vp, name, attr, &vp, flags, - cr, &ct, vsap); + cr, vsap); } if (vsap != NULL) @@ -226,7 +224,7 @@ smb_fsop_create_with_sd( if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) no_xvattr = B_TRUE; rc = smb_vop_setattr(snode->vp, NULL, &set_attr, - 0, kcred, no_xvattr, &ct); + 0, kcred, no_xvattr); } } else { @@ -241,10 +239,10 @@ smb_fsop_create_with_sd( if (is_dir) { rc = smb_vop_mkdir(snode->vp, name, attr, &vp, flags, - cr, &ct, NULL); + cr, NULL); } else { rc = smb_vop_create(snode->vp, name, attr, &vp, flags, - cr, &ct, NULL); + cr, NULL); } if (rc != 0) @@ -266,9 +264,9 @@ smb_fsop_create_with_sd( if (rc != 0) { if (is_dir) { - (void) smb_vop_rmdir(snode->vp, name, flags, cr, &ct); + (void) smb_vop_rmdir(snode->vp, name, flags, cr); } else { - (void) smb_vop_remove(snode->vp, name, flags, cr, &ct); + (void) smb_vop_remove(snode->vp, name, flags, cr); } } @@ -303,7 +301,6 @@ smb_fsop_create( struct open_param *op = &sr->arg.open; smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; vnode_t *xattrdirvp; vnode_t *vp; char *longname = NULL; @@ -397,10 +394,8 @@ smb_fsop_create( return (rc); } - smb_get_caller_context(sr, &ct); - rc = smb_vop_stream_create(fnode->vp, sname, attr, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if (rc != 0) { smb_node_release(fnode); @@ -457,9 +452,8 @@ smb_fsop_create( * No incoming SD and filesystem is not ZFS * let the filesystem handles the inheritance. */ - smb_get_caller_context(sr, &ct); rc = smb_vop_create(dir_snode->vp, name, attr, &vp, - flags, cr, &ct, NULL); + flags, cr, NULL); if (rc == 0) { *ret_snode = smb_node_lookup(sr, op, cr, vp, @@ -503,7 +497,6 @@ smb_fsop_mkdir( smb_attr_t *ret_attr) { struct open_param *op = &sr->arg.open; - caller_context_t ct; char *longname; vnode_t *vp; int flags = 0; @@ -511,7 +504,6 @@ smb_fsop_mkdir( uint32_t secinfo; uint32_t status; int rc; - ASSERT(cr); ASSERT(dir_snode); ASSERT(dir_snode->n_magic == SMB_NODE_MAGIC); @@ -557,8 +549,6 @@ smb_fsop_mkdir( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - if (op->sd) { /* * SD sent by client in Windows format. Needs to be @@ -592,7 +582,7 @@ smb_fsop_mkdir( } else { rc = smb_vop_mkdir(dir_snode->vp, name, attr, &vp, flags, cr, - &ct, NULL); + NULL); if (rc == 0) { *ret_snode = smb_node_lookup(sr, op, cr, vp, name, @@ -632,7 +622,6 @@ smb_fsop_remove( { smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; char *longname; char *fname; char *sname; @@ -654,8 +643,6 @@ smb_fsop_remove( if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - smb_get_caller_context(sr, &ct); - fname = kmem_alloc(MAXNAMELEN, KM_SLEEP); sname = kmem_alloc(MAXNAMELEN, KM_SLEEP); @@ -687,7 +674,7 @@ smb_fsop_remove( * Need to find out what permission is required by NTFS * to remove a stream. */ - rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr, &ct); + rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr); smb_node_release(fnode); } else { @@ -705,7 +692,7 @@ smb_fsop_remove( if ((od == 0) && SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - rc = smb_vop_remove(dir_snode->vp, name, flags, cr, &ct); + rc = smb_vop_remove(dir_snode->vp, name, flags, cr); if (rc == ENOENT) { if (smb_maybe_mangled_name(name) == 0) { @@ -729,7 +716,7 @@ smb_fsop_remove( */ flags &= ~SMB_IGNORE_CASE; rc = smb_vop_remove(dir_snode->vp, longname, - flags, cr, &ct); + flags, cr); } kmem_free(longname, MAXNAMELEN); @@ -754,7 +741,6 @@ smb_fsop_remove_streams(struct smb_request *sr, cred_t *cr, smb_node_t *fnode) { struct fs_stream_info stream_info; - caller_context_t ct; uint32_t cookie = 0; int flags = 0; int rc; @@ -773,17 +759,15 @@ smb_fsop_remove_streams(struct smb_request *sr, cred_t *cr, if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - for (;;) { rc = smb_vop_stream_readdir(fnode->vp, &cookie, &stream_info, - NULL, NULL, flags, cr, &ct); + NULL, NULL, flags, cr); if ((rc != 0) || (cookie == SMB_EOF)) break; (void) smb_vop_stream_remove(fnode->vp, stream_info.name, flags, - cr, &ct); + cr); } return (rc); } @@ -809,7 +793,6 @@ smb_fsop_rmdir( char *name, int od) { - caller_context_t ct; int rc; int flags = 0; char *longname; @@ -843,9 +826,7 @@ smb_fsop_rmdir( if ((od == 0) && SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - - rc = smb_vop_rmdir(dir_snode->vp, name, flags, cr, &ct); + rc = smb_vop_rmdir(dir_snode->vp, name, flags, cr); if (rc == ENOENT) { if (smb_maybe_mangled_name(name) == 0) @@ -867,8 +848,7 @@ smb_fsop_rmdir( * a unique directory. */ flags &= ~SMB_IGNORE_CASE; - rc = smb_vop_rmdir(dir_snode->vp, longname, flags, cr, - &ct); + rc = smb_vop_rmdir(dir_snode->vp, longname, flags, cr); } kmem_free(longname, MAXNAMELEN); @@ -893,10 +873,10 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; uint32_t status; uint32_t access = 0; int flags = 0; + int rc; ASSERT(cr); ASSERT(snode); @@ -923,8 +903,6 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, flags = ATTR_NOACLCHECK; } - smb_get_caller_context(sr, &ct); - unnamed_node = SMB_IS_STREAM(snode); if (unnamed_node) { @@ -933,7 +911,11 @@ smb_fsop_getattr(struct smb_request *sr, cred_t *cr, smb_node_t *snode, unnamed_vp = unnamed_node->vp; } - return (smb_vop_getattr(snode->vp, unnamed_vp, attr, flags, cr, &ct)); + rc = smb_vop_getattr(snode->vp, unnamed_vp, attr, flags, cr); + if (rc == 0) + snode->attr = *attr; + + return (rc); } /* @@ -959,7 +941,6 @@ smb_fsop_readdir( smb_node_t **ret_snode, smb_attr_t *ret_attr) { - caller_context_t ct; smb_node_t *ret_snodep; smb_node_t *fnode; smb_attr_t tmp_attr; @@ -986,13 +967,11 @@ smb_fsop_readdir( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - 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, &ct); + SMB_FOLLOW_LINKS, sr->tid_tree->t_snode->vp, cr); if (rc != 0) { kmem_free(od_name, MAXNAMELEN); @@ -1017,7 +996,7 @@ smb_fsop_readdir( * Might have to use kcred. */ rc = smb_vop_stream_readdir(fvp, cookie, stream_info, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if ((rc != 0) || (*cookie == SMB_EOF)) { smb_node_release(fnode); @@ -1047,7 +1026,7 @@ smb_fsop_readdir( } else { rc = smb_vop_readdir(dir_snode->vp, cookie, name, namelen, - fileid, &vp, od_name, flags, cr, &ct); + fileid, &vp, od_name, flags, cr); if (rc != 0) { kmem_free(od_name, MAXNAMELEN); @@ -1104,7 +1083,6 @@ smb_fsop_getdents( char *args, char *pattern) { - caller_context_t ct; int flags = 0; ASSERT(cr); @@ -1118,10 +1096,8 @@ smb_fsop_getdents( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - return (smb_vop_getdents(dir_snode, cookie, 0, maxcnt, args, pattern, - flags, sr, cr, &ct)); + flags, sr, cr)); } /* @@ -1145,7 +1121,6 @@ smb_fsop_rename( char *to_name) { smb_node_t *from_snode; - caller_context_t ct; smb_attr_t tmp_attr; vnode_t *from_vp; int flags = 0; @@ -1188,16 +1163,14 @@ smb_fsop_rename( * XXX: Lock required through smb_node_release() below? */ - smb_get_caller_context(sr, &ct); - rc = smb_vop_lookup(from_dir_snode->vp, from_name, &from_vp, NULL, 0, - NULL, cr, &ct); + NULL, cr); if (rc != 0) return (rc); rc = smb_vop_rename(from_dir_snode->vp, from_name, to_dir_snode->vp, - to_name, flags, cr, &ct); + to_name, flags, cr); if (rc == 0) { from_snode = smb_node_lookup(sr, NULL, cr, from_vp, from_name, @@ -1242,7 +1215,6 @@ smb_fsop_setattr( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; uint32_t status; uint32_t access = 0; int rc = 0; @@ -1278,8 +1250,6 @@ smb_fsop_setattr( flags = ATTR_NOACLCHECK; } - smb_get_caller_context(sr, &ct); - unnamed_node = SMB_IS_STREAM(snode); if (unnamed_node) { @@ -1291,18 +1261,18 @@ smb_fsop_setattr( if (sr->tid_tree->t_flags & SMB_TREE_FLAG_UFS) no_xvattr = B_TRUE; - rc = smb_vop_setattr(snode->vp, unnamed_vp, - set_attr, flags, cr, no_xvattr, &ct); + rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr, + no_xvattr); if ((rc == 0) && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + rc = smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, kcred); + if (rc == 0) + snode->attr = *ret_attr; } return (rc); @@ -1328,7 +1298,7 @@ smb_fsop_read( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; + int svmand; int rc; ASSERT(cr); @@ -1360,20 +1330,36 @@ smb_fsop_read( cr = kcred; } - smb_get_caller_context(sr, &ct); - rc = smb_vop_read(snode->vp, uio, cr, &ct); + smb_node_start_crit(snode, RW_READER); + rc = nbl_svmand(snode->vp, cr, &svmand); + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + + rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset, + uio->uio_iov->iov_len, svmand, &smb_ct); - if (rc == 0) { + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = smb_vop_read(snode->vp, uio, cr); + + if (rc == 0 && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + if (smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, + kcred) == 0) { + snode->attr = *ret_attr; + } } + smb_node_end_crit(snode); + return (rc); } @@ -1396,7 +1382,7 @@ smb_fsop_write( { smb_node_t *unnamed_node; vnode_t *unnamed_vp = NULL; - caller_context_t ct; + int svmand; int rc; ASSERT(cr); @@ -1410,15 +1396,13 @@ smb_fsop_write( if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - /* - * XXX what if the file has been opened only with - * FILE_APPEND_DATA? - */ - rc = smb_ofile_access(sr->fid_ofile, cr, FILE_WRITE_DATA); - if (rc != NT_STATUS_SUCCESS) - return (EACCES); - smb_get_caller_context(sr, &ct); + rc = smb_ofile_access(sr->fid_ofile, cr, FILE_WRITE_DATA); + if (rc != NT_STATUS_SUCCESS) { + rc = smb_ofile_access(sr->fid_ofile, cr, FILE_APPEND_DATA); + if (rc != NT_STATUS_SUCCESS) + return (EACCES); + } unnamed_node = SMB_IS_STREAM(snode); @@ -1435,19 +1419,35 @@ smb_fsop_write( cr = kcred; } - rc = smb_vop_write(snode->vp, uio, flag, lcount, cr, &ct); + smb_node_start_crit(snode, RW_READER); + rc = nbl_svmand(snode->vp, cr, &svmand); + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = nbl_lock_conflict(snode->vp, NBL_WRITE, uio->uio_loffset, + uio->uio_iov->iov_len, svmand, &smb_ct); - if (rc == 0) { + if (rc) { + smb_node_end_crit(snode); + return (rc); + } + rc = smb_vop_write(snode->vp, uio, flag, lcount, cr); + + if (rc == 0 && ret_attr) { /* - * This is an operation on behalf of CIFS service (to update - * smb node's attr) not on behalf of the user so it's done - * using kcred and the return value is intentionally ignored. + * Use kcred to update the node attr because this + * call is not being made on behalf of the user. */ ret_attr->sa_mask = SMB_AT_ALL; - (void) smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, - kcred, &ct); + if (smb_vop_getattr(snode->vp, unnamed_vp, ret_attr, 0, + kcred) == 0) { + snode->attr = *ret_attr; + } } + smb_node_end_crit(snode); + return (rc); } @@ -1577,7 +1577,6 @@ smb_fsop_lookup_name( { smb_node_t *fnode; smb_attr_t file_attr; - caller_context_t ct; vnode_t *xattrdirvp; vnode_t *vp; char *od_name; @@ -1627,7 +1626,7 @@ smb_fsop_lookup_name( * What permissions NTFS requires for stream lookup if any? */ rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name, - &xattrdirvp, flags, root_node->vp, cr, &ct); + &xattrdirvp, flags, root_node->vp, cr); if (rc != 0) { smb_node_release(fnode); @@ -1707,7 +1706,6 @@ smb_fsop_lookup( { smb_node_t *lnk_target_node; smb_node_t *lnk_dnode; - caller_context_t ct; char *longname; char *od_name; vnode_t *vp; @@ -1727,12 +1725,10 @@ smb_fsop_lookup( if (SMB_TREE_CASE_INSENSITIVE(sr)) flags |= SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP); rc = smb_vop_lookup(dir_snode->vp, name, &vp, od_name, flags, - root_node ? root_node->vp : NULL, cr, &ct); + root_node ? root_node->vp : NULL, cr); if (rc != 0) { if (smb_maybe_mangled_name(name) == 0) { @@ -1764,7 +1760,7 @@ smb_fsop_lookup( flags &= ~SMB_IGNORE_CASE; rc = smb_vop_lookup(dir_snode->vp, longname, &vp, od_name, - flags, root_node ? root_node->vp : NULL, cr, &ct); + flags, root_node ? root_node->vp : NULL, cr); kmem_free(longname, MAXNAMELEN); @@ -1871,7 +1867,6 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, smb_node_t **ret_snode, smb_attr_t *ret_attr) { smb_node_t *ret_snodep = NULL; - caller_context_t ct; smb_attr_t tmp_attr; vnode_t *xattrdirvp; vnode_t *vp; @@ -1889,10 +1884,8 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, if (SMB_TREE_CASE_INSENSITIVE(sr)) flags = SMB_IGNORE_CASE; - smb_get_caller_context(sr, &ct); - rc = smb_vop_stream_readdir(fnode->vp, cookiep, stream_info, &vp, - &xattrdirvp, flags, cr, &ct); + &xattrdirvp, flags, cr); if ((rc != 0) || *cookiep == SMB_EOF) return (rc); @@ -1922,8 +1915,6 @@ smb_fsop_stream_readdir(struct smb_request *sr, cred_t *cr, smb_node_t *fnode, int /*ARGSUSED*/ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode) { - caller_context_t ct; - ASSERT(cr); ASSERT(snode); ASSERT(snode->n_magic == SMB_NODE_MAGIC); @@ -1934,9 +1925,7 @@ smb_fsop_commit(smb_request_t *sr, cred_t *cr, smb_node_t *snode) if (SMB_TREE_IS_READ_ONLY(sr)) return (EROFS); - smb_get_caller_context(sr, &ct); - - return (smb_vop_commit(snode->vp, cr, &ct)); + return (smb_vop_commit(snode->vp, cr)); } /* @@ -1961,7 +1950,6 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, int flags = 0; int access = 0; acl_t *acl; - caller_context_t ct; smb_node_t *unnamed_node; ASSERT(cr); @@ -1993,9 +1981,8 @@ smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode, if (sr->tid_tree->t_flags & SMB_TREE_FLAG_ACEMASKONACCESS) flags = ATTR_NOACLCHECK; - smb_get_caller_context(sr, &ct); error = smb_vop_acl_read(snode->vp, &acl, flags, - sr->tid_tree->t_acltype, cr, &ct); + sr->tid_tree->t_acltype, cr); if (error != 0) { return (error); } @@ -2025,7 +2012,6 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, int error = 0; int flags = 0; int access = 0; - caller_context_t ct; acl_t *acl, *dacl, *sacl; smb_node_t *unnamed_node; @@ -2088,11 +2074,10 @@ smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode, error = acl_translate(acl, target_flavor, (snode->vp->v_type == VDIR), fs_sd->sd_uid, fs_sd->sd_gid); if (error == 0) { - smb_get_caller_context(sr, &ct); if (sr->tid_tree->t_flags & SMB_TREE_FLAG_ACEMASKONACCESS) flags = ATTR_NOACLCHECK; - error = smb_vop_acl_write(snode->vp, acl, flags, cr, &ct); + error = smb_vop_acl_write(snode->vp, acl, flags, cr); } if (dacl && sacl) @@ -2474,11 +2459,131 @@ smb_fsop_eaccess(smb_request_t *sr, cred_t *cr, smb_node_t *snode, FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD; } -/*ARGSUSED*/ +/* + * smb_fsop_shrlock + * + * For the current open request, check file sharing rules + * against existing opens. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict. Returns NT_STATUS_SUCCESS otherwise. + * + * Full system-wide share reservation synchronization is available + * when the nbmand (non-blocking mandatory) mount option is set + * (i.e. nbl_need_crit() is true) and nbmand critical regions are used. + * This provides synchronization with NFS and local processes. The + * critical regions are entered in VOP_SHRLOCK()/fs_shrlock() (called + * from smb_open_subr()/smb_fsop_shrlock()/smb_vop_shrlock()) as well + * as the CIFS rename and delete paths. + * + * The CIFS server will also enter the nbl critical region in the open, + * rename, and delete paths when nbmand is not set. There is limited + * coordination with local and VFS share reservations in this case. + * Note that when the nbmand mount option is not set, the VFS layer + * only processes advisory reservations and the delete mode is not checked. + * + * Whether or not the nbmand mount option is set, intra-CIFS share + * checking is done in the open, delete, and rename paths using a CIFS + * critical region (node->n_share_lock). + */ + +uint32_t +smb_fsop_shrlock(cred_t *cr, struct smb_node *node, uint32_t uniq_fid, + uint32_t desired_access, uint32_t share_access) +{ + int rc; + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + /* Allow access if the request is just for meta data */ + if ((desired_access & FILE_DATA_ALL) == 0) + return (NT_STATUS_SUCCESS); + + rc = smb_node_open_check(node, cr, desired_access, share_access); + if (rc) + return (NT_STATUS_SHARING_VIOLATION); + + rc = smb_vop_shrlock(node->vp, uniq_fid, desired_access, share_access, + cr); + if (rc) + return (NT_STATUS_SHARING_VIOLATION); + + return (NT_STATUS_SUCCESS); +} + void -smb_get_caller_context(smb_request_t *sr, caller_context_t *ct) +smb_fsop_unshrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid) +{ + if (node->attr.sa_vattr.va_type == VDIR) + return; + + (void) smb_vop_unshrlock(node->vp, uniq_fid, cr); +} + +/* + * smb_fsop_frlock_callback + * + * smb wrapper function for fs_frlock + * this should never happen, as we are not attempting + * to set Mandatory Locks, cmd = F_SETLK_NBMAND + * + */ + +static callb_cpr_t * +/* ARGSUSED */ +smb_fsop_frlock_callback(flk_cb_when_t when, void *error) { - ct->cc_caller_id = smb_caller_id; - ct->cc_pid = 0; /* TBD */ - ct->cc_sysid = 0; /* TBD */ + return (0); +} + +/* + * smb_fs_frlock + * + * smb wrapper function for fs_frlock + */ + +int +smb_fsop_frlock(smb_request_t *sr, smb_node_t *node, smb_lock_t *lock, + boolean_t unlock) +{ + vnode_t *vp; + flock64_t bf; + cred_t *cr; + caller_context_t *ct; + int cmd; + flk_callback_t flk_cb; + offset_t offset = 0; + int flag; + int error; + int i; + + flk_init_callback(&flk_cb, smb_fsop_frlock_callback, &error); + cr = sr->user_cr; + ct = &smb_ct; + vp = node->vp; + cmd = F_SETLK; + + if (unlock == B_TRUE) { + bf.l_type = F_UNLCK; + flag = 0; + } else if (lock->l_type == SMB_LOCK_TYPE_READONLY) { + bf.l_type = F_RDLCK; + flag = FREAD; + } else if (lock->l_type == SMB_LOCK_TYPE_READWRITE) { + bf.l_type = F_WRLCK; + flag = FWRITE; + } + + bf.l_start = lock->l_start; + bf.l_len = lock->l_length; + bf.l_whence = 0; /* SEEK_SET */ + bf.l_pid = lock->l_pid; + bf.l_sysid = 0; + + for (i = 0; i < 4; i++) + bf.l_pad[i] = 0; + + error = fs_frlock(vp, cmd, &bf, flag, offset, &flk_cb, cr, ct); + return (error); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c index cb5aa042ee..d9773cb50f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,7 +76,7 @@ smb_com_lock_byte_range(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -90,7 +90,7 @@ smb_com_lock_byte_range(struct smb_request *sr) result = smb_lock_range(sr, sr->fid_ofile, (u_offset_t)off, (uint64_t)count, 0, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c index 7326d5a12c..b39188ebbd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_svc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,17 @@ */ #include <smbsrv/smb_incl.h> +#include <smbsrv/smb_fsops.h> +#include <sys/nbmlock.h> +#include <sys/param.h> + +static void +smb_unlock_to_posix_unlock(smb_request_t *sr, smb_node_t *node, + smb_lock_t *lock, boolean_t unlock); + +static boolean_t +smb_is_range_unlocked(uint64_t start, uint64_t end, smb_llist_t *llist_head, + uint64_t *new_mark); static int smb_lock_range_overlap(struct smb_lock *lock, uint64_t start, uint64_t length); @@ -367,6 +378,9 @@ smb_unlock_range( } smb_llist_remove(&node->n_lock_list, lock); + + smb_unlock_to_posix_unlock(sr, node, lock, B_TRUE); + smb_llist_exit(&node->n_lock_list); smb_lock_destroy(lock); @@ -481,7 +495,14 @@ smb_lock_range( smb_lock_free(lock); } else { - smb_llist_insert_tail(&node->n_lock_list, lock); + /* + * don't insert into the CIFS lock list unless the + * posix lock worked + */ + if (smb_fsop_frlock(sr, node, lock, B_FALSE)) + result = NT_STATUS_FILE_LOCK_CONFLICT; + else + smb_llist_insert_tail(&node->n_lock_list, lock); } smb_llist_exit(&node->n_lock_list); @@ -506,15 +527,12 @@ smb_lock_range_access( struct smb_node *node, uint64_t start, uint64_t length, - uint32_t desired_access) + boolean_t will_write) { smb_lock_t *lock; smb_llist_t *llist; int status = NT_STATUS_SUCCESS; - ASSERT((desired_access & ~(FILE_READ_DATA | FILE_WRITE_DATA)) == 0); - ASSERT((desired_access & (FILE_READ_DATA | FILE_WRITE_DATA)) != 0); - llist = &node->n_lock_list; smb_llist_enter(llist, RW_READER); /* Search for any applicable lock */ @@ -526,8 +544,7 @@ smb_lock_range_access( /* Lock does not overlap */ continue; - if (lock->l_type == SMB_LOCK_TYPE_READONLY && - desired_access == FILE_READ_DATA) + if (lock->l_type == SMB_LOCK_TYPE_READONLY && !will_write) continue; if (lock->l_type == SMB_LOCK_TYPE_READWRITE && @@ -664,46 +681,196 @@ smb_node_destroy_lock_by_ofile(smb_node_t *node, smb_ofile_t *file) } void -smb_lock_range_raise_error(smb_request_t *sr, uint32_t ntstatus) +smb_lock_range_error(smb_request_t *sr, uint32_t status32) { - switch (ntstatus) { - case NT_STATUS_CANCELLED: - /* - * XXX What is the proper error here? - */ - smbsr_raise_error(sr, ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_FILE_LOCK_CONFLICT: - smbsr_raise_cifs_error(sr, NT_STATUS_FILE_LOCK_CONFLICT, - ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_LOCK_NOT_GRANTED: - smbsr_raise_cifs_error(sr, NT_STATUS_LOCK_NOT_GRANTED, - ERRDOS, ERRlock); - /* NOTREACHED */ - case NT_STATUS_RANGE_NOT_LOCKED: - smbsr_raise_cifs_error(sr, NT_STATUS_RANGE_NOT_LOCKED, - ERRDOS, ERRlock); - /* NOTREACHED */ - default: - ASSERT(0); - smbsr_raise_error(sr, ERRDOS, ntstatus); - /* NOTREACHED */ + uint16_t errcode; + + if (status32 == NT_STATUS_CANCELLED) + errcode = ERROR_OPERATION_ABORTED; + else + errcode = ERRlock; + + smbsr_error(sr, status32, ERRDOS, errcode); + /* NOTREACHED */ +} + +/* + * smb_range_check() + * + * Perform range checking. First check for internal CIFS range conflicts + * and then check for external conflicts, for example, with NFS or local + * access. + * + * If nbmand is enabled, this function must be called from within an nbmand + * critical region + */ + +DWORD +smb_range_check(smb_request_t *sr, cred_t *cr, smb_node_t *node, uint64_t start, + uint64_t length, boolean_t will_write) +{ + smb_error_t smberr; + int svmand; + int nbl_op; + int rc; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + ASSERT(smb_node_in_crit(node)); + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + rc = smb_lock_range_access(sr, node, start, length, will_write); + if (rc) + return (NT_STATUS_UNSUCCESSFUL); + + if ((rc = nbl_svmand(node->vp, cr, &svmand)) != 0) { + smbsr_map_errno(rc, &smberr); + return (smberr.status); } + + if (will_write) + nbl_op = NBL_WRITE; + else + nbl_op = NBL_READ; + + if (nbl_lock_conflict(node->vp, nbl_op, start, length, + svmand, &smb_ct)) + return (NT_STATUS_UNSUCCESSFUL); + + return (NT_STATUS_SUCCESS); } +/* + * smb_unlock_to_posix_unlock + * + * checks if the current unlock request is in another lock + * and repeatedly calls smb_is_range_unlocked on a sliding basis to + * to unlock all bits of the lock that are not in other locks + * + */ void -smb_unlock_range_raise_error(smb_request_t *sr, uint32_t ntstatus) +smb_unlock_to_posix_unlock(smb_request_t *sr, smb_node_t *node, + smb_lock_t *lock, boolean_t unlock) { - switch (ntstatus) { - case NT_STATUS_RANGE_NOT_LOCKED: - smbsr_raise_cifs_error(sr, NT_STATUS_RANGE_NOT_LOCKED, - ERRDOS, ERRnotlocked); - /* NOTREACHED */ - default: - ASSERT(0); - smbsr_raise_error(sr, ERRDOS, ntstatus); - /* NOTREACHED */ + uint64_t new_mark; + uint64_t unlock_start; + uint64_t unlock_end; + boolean_t unlocked; + smb_lock_t new_unlock; + smb_llist_t *llist_head; + int cnt = 1; + + new_mark = 0; + unlock_start = lock->l_start; + unlock_end = unlock_start + lock->l_length; + llist_head = &node->n_lock_list; + + while (cnt) { + if ((unlocked = smb_is_range_unlocked(unlock_start, unlock_end, + llist_head, &new_mark)) == B_TRUE) { + if (new_mark) { + new_unlock = *lock; + new_unlock.l_start = unlock_start; + new_unlock.l_length = new_mark - unlock_start; + (void) smb_fsop_frlock(sr, node, + &new_unlock, unlock); + unlock_start = new_mark; + } else { + new_unlock = *lock; + new_unlock.l_start = unlock_start; + new_unlock.l_length = unlock_end - unlock_start; + (void) smb_fsop_frlock(sr, node, + &new_unlock, unlock); + break; + } + } else if ((unlocked == B_FALSE) && new_mark) { + unlock_start = new_mark; + } else { + break; + } + } +} + +/* + * smb_is_range_unlocked + * + * Checks if the current unlock byte range request overlaps another lock + * The return code and the value of new_mark must be interpreted as + * follows: + * + * B_TRUE and (new_mark == 0): + * This is the last or only lock left to be unlocked + * + * B_TRUE and (new_mark > 0): + * The range from start to new_mark can be unlocked + * + * B_FALSE and (new_mark == 0): + * The unlock can't be performed and we are done + * + * B_FALSE and (new_mark > 0), + * The range from start to new_mark can't be unlocked + * Start should be reset to new_mark for the next pass + */ + +static boolean_t +smb_is_range_unlocked(uint64_t start, uint64_t end, smb_llist_t *llist_head, + uint64_t *new_mark) +{ + struct smb_lock *lk = 0; + uint64_t low_water_mark = MAXOFFSET_T; + uint64_t lk_start; + uint64_t lk_end; + + *new_mark = 0; + lk = smb_llist_head(llist_head); + while (lk) { + + lk_end = lk->l_start + lk->l_length - 1; + lk_start = lk->l_start; + + /* + * there is no overlap for the first 2 cases + * check next node + */ + if (lk_end < start) { + lk = smb_llist_next(llist_head, lk); + continue; + } + if (lk_start > end) { + lk = smb_llist_next(llist_head, lk); + continue; + } + + /* this range is completely locked */ + if ((lk_start <= start) && (lk_end >= end)) { + return (B_FALSE); + } + + /* the first part of this range is locked */ + if ((start >= lk_start) && (start <= lk_end)) { + if (end > lk_end) + *new_mark = lk_end + 1; + return (B_FALSE); + } + + /* this piece is unlocked */ + if ((lk_start >= start) && (lk_start <= end)) { + if (low_water_mark > lk_start) + low_water_mark = lk_start; + } + + lk = smb_llist_next(llist_head, lk); + } + + if (low_water_mark != MAXOFFSET_T) { + *new_mark = low_water_mark; + return (B_TRUE); } + /* the range is completely unlocked */ + return (B_TRUE); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c index 0acf7922c4..4aa585091e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -239,8 +239,7 @@ smb_com_locking_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -275,7 +274,7 @@ smb_com_locking_andx(struct smb_request *sr) * implement this) */ if (lock_type & LOCKING_ANDX_CHANGE_LOCK_TYPE) { - smbsr_raise_error(sr, ERRDOS, ERRnoatomiclocks); + smbsr_error(sr, 0, ERRDOS, ERRnoatomiclocks); /* NOT REACHED */ } @@ -283,8 +282,7 @@ smb_com_locking_andx(struct smb_request *sr) * No support for cancel lock (smbtorture expects this) */ if (lock_type & LOCKING_ANDX_CANCEL_LOCK) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOT REACHED */ } @@ -294,8 +292,7 @@ smb_com_locking_andx(struct smb_request *sr) * negotiated protocol should be NT LM 0.12 or later */ if (sr->session->dialect < NT_LM_0_12) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOT REACHED */ } @@ -305,17 +302,18 @@ smb_com_locking_andx(struct smb_request *sr) &sr->smb_pid, &offset64, &length64); if (rc) { /* - * This is the error returned by a W2K system - * even when NT Status is negotiated. + * This is the error returned by Windows 2000 + * even when STATUS32 has been negotiated. */ - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, offset64, length64); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } } @@ -324,14 +322,14 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "w2.QQ", &sr->smb_pid, &offset64, &length64); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_lock_range(sr, sr->fid_ofile, offset64, length64, timeout, ltype); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } } @@ -340,14 +338,15 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, &offset32, &length32); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, (uint64_t)offset32, (uint64_t)length32); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } } @@ -356,7 +355,7 @@ smb_com_locking_andx(struct smb_request *sr) rc = smb_decode_mbc(&sr->smb_data, "wll", &sr->smb_pid, &offset32, &length32); if (rc) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOT REACHED */ } @@ -365,7 +364,7 @@ smb_com_locking_andx(struct smb_request *sr) (uint64_t)length32, timeout, ltype); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); /* NOT REACHED */ } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c index 278916b8fd..4b56c61b73 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,8 +66,7 @@ int smb_com_logoff_andx(struct smb_request *sr) { if (sr->uid_user == NULL) { - cmn_err(CE_WARN, "SmbLogoffAndX: bad uid"); - smbsr_raise_error(sr, ERRSRV, ERRbaduid); + smbsr_error(sr, 0, ERRSRV, ERRbaduid); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c index 844e84a889..a14ae7d3a5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c +++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -261,7 +261,7 @@ smb_com_negotiate(struct smb_request *sr) if (sr->session->s_state != SMB_SESSION_STATE_ESTABLISHED) { /* The protocol has already been negotiated. */ - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -269,7 +269,7 @@ smb_com_negotiate(struct smb_request *sr) sr->smb_data.chain_offset < sr->smb_data.max_bytes; pos++) { if (smb_decode_mbc(&sr->smb_data, "%L", sr, &p) != 0) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -284,7 +284,7 @@ smb_com_negotiate(struct smb_request *sr) } } if (sel_pos < 0) { - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } @@ -435,9 +435,7 @@ smb_com_negotiate(struct smb_request *sr) break; default: - /* Just to make sure. */ - ASSERT(0); - smbsr_raise_error(sr, ERRSRV, ERRerror); + smbsr_error(sr, 0, ERRSRV, ERRerror); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c index 5ea8c5f1c3..13be0f3cf3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_node.c +++ b/usr/src/uts/common/fs/smbsrv/smb_node.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -84,6 +84,7 @@ #include <smbsrv/smb_fsops.h> #include <sys/pathname.h> #include <sys/sdt.h> +#include <sys/nbmlock.h> uint32_t smb_is_executable(char *path); static void smb_node_delete_on_close(smb_node_t *node); @@ -138,7 +139,6 @@ smb_node_lookup( fs_desc_t fsd; int error; krw_t lock_mode; - caller_context_t ct; vnode_t *unnamed_vp = NULL; /* @@ -154,9 +154,8 @@ smb_node_lookup( * This getattr is performed on behalf of the server * that's why kcred is used not the user's cred */ - smb_get_caller_context(sr, &ct); attr->sa_mask = SMB_AT_ALL; - error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred, &ct); + error = smb_vop_getattr(vp, unnamed_vp, attr, 0, kcred); if (error) return (NULL); @@ -208,6 +207,7 @@ smb_node_lookup( smb_node_ref(dir_snode); } node->attr = *attr; + node->n_size = attr->sa_vattr.va_size; smb_audit_node(node); smb_rwx_xexit(&node->n_lock); @@ -768,3 +768,252 @@ smb_node_reset_delete_on_close(smb_node_t *node) } smb_rwx_xexit(&node->n_lock); } + +/* + * smb_node_share_check + * + * check file sharing rules for current open request + * against all existing opens for a file. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict, otherwise returns NT_STATUS_SUCCESS. + */ +uint32_t +smb_node_open_check(struct smb_node *node, cred_t *cr, + uint32_t desired_access, uint32_t share_access) +{ + smb_ofile_t *of; + uint32_t status; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + smb_llist_enter(&node->n_ofile_list, RW_READER); + of = smb_llist_head(&node->n_ofile_list); + while (of) { + status = smb_node_share_check(node, cr, desired_access, + share_access, of); + if (status == NT_STATUS_SHARING_VIOLATION) { + smb_llist_exit(&node->n_ofile_list); + return (status); + } + of = smb_llist_next(&node->n_ofile_list, of); + } + smb_llist_exit(&node->n_ofile_list); + + return (NT_STATUS_SUCCESS); +} + +/* + * smb_open_share_check + * + * check file sharing rules for current open request + * against the given existing open. + * + * Returns NT_STATUS_SHARING_VIOLATION if there is any + * sharing conflict, otherwise returns NT_STATUS_SUCCESS. + */ +uint32_t +smb_node_share_check( + struct smb_node *node, + cred_t *cr, + uint32_t desired_access, + uint32_t share_access, + smb_ofile_t *of) +{ + /* + * It appears that share modes are not relevant to + * directories, but this check will remain as it is not + * clear whether it was originally put here for a reason. + */ + if (node->attr.sa_vattr.va_type == VDIR) { + if (SMB_DENY_RW(of->f_share_access) && + (node->n_orig_uid != crgetuid(cr))) { + return (NT_STATUS_SHARING_VIOLATION); + } + + return (NT_STATUS_SUCCESS); + } + + /* if it's just meta data */ + if ((of->f_granted_access & FILE_DATA_ALL) == 0) + return (NT_STATUS_SUCCESS); + + /* + * Check requested share access against the + * open granted (desired) access + */ + if (SMB_DENY_DELETE(share_access) && (of->f_granted_access & DELETE)) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_READ(share_access) && + (of->f_granted_access & (FILE_READ_DATA | FILE_EXECUTE))) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_WRITE(share_access) && + (of->f_granted_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) + return (NT_STATUS_SHARING_VIOLATION); + + /* check requested desired access against the open share access */ + if (SMB_DENY_DELETE(of->f_share_access) && (desired_access & DELETE)) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_READ(of->f_share_access) && + (desired_access & (FILE_READ_DATA | FILE_EXECUTE))) + return (NT_STATUS_SHARING_VIOLATION); + + if (SMB_DENY_WRITE(of->f_share_access) && + (desired_access & (FILE_WRITE_DATA | FILE_APPEND_DATA))) + return (NT_STATUS_SHARING_VIOLATION); + + return (NT_STATUS_SUCCESS); +} + +/* + * smb_rename_share_check + * + * An open file can be renamed if + * + * 1. isn't opened for data writing or deleting + * + * 2. Opened with "Deny Delete" share mode + * But not opened for data reading or executing + * (opened for accessing meta data) + */ + +DWORD +smb_node_rename_check(struct smb_node *node) +{ + struct smb_ofile *open; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + /* + * Intra-CIFS check + */ + + smb_llist_enter(&node->n_ofile_list, RW_READER); + open = smb_llist_head(&node->n_ofile_list); + while (open) { + if (open->f_granted_access & + (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + + if ((open->f_share_access & FILE_SHARE_DELETE) == 0) { + if (open->f_granted_access & + (FILE_READ_DATA | FILE_EXECUTE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + } + open = smb_llist_next(&node->n_ofile_list, open); + } + smb_llist_exit(&node->n_ofile_list); + + /* + * system-wide share check + */ + + if (nbl_share_conflict(node->vp, NBL_RENAME, NULL)) + return (NT_STATUS_SHARING_VIOLATION); + else + return (NT_STATUS_SUCCESS); +} + +/* + * smb_node_delete_check + * + * An open file can be deleted only if opened for + * accessing meta data. Share modes aren't important + * in this case. + * + * NOTE: there is another mechanism for deleting an + * open file that NT clients usually use. + * That's setting "Delete on close" flag for an open + * file. In this way the file will be deleted after + * last close. This flag can be set by SmbTrans2SetFileInfo + * with FILE_DISPOSITION_INFO information level. + * For setting this flag, the file should be opened by + * DELETE access in the FID that is passed in the Trans2 + * request. + */ +DWORD +smb_node_delete_check(smb_node_t *node) +{ + smb_ofile_t *file; + + ASSERT(node); + ASSERT(node->n_magic == SMB_NODE_MAGIC); + ASSERT(node->n_state == SMB_NODE_STATE_AVAILABLE); + + if (node->attr.sa_vattr.va_type == VDIR) + return (NT_STATUS_SUCCESS); + + /* + * intra-CIFS check + */ + + smb_llist_enter(&node->n_ofile_list, RW_READER); + file = smb_llist_head(&node->n_ofile_list); + while (file) { + ASSERT(file->f_magic == SMB_OFILE_MAGIC); + if (file->f_granted_access & + (FILE_READ_DATA | + FILE_WRITE_DATA | + FILE_APPEND_DATA | + FILE_EXECUTE | + DELETE)) { + smb_llist_exit(&node->n_ofile_list); + return (NT_STATUS_SHARING_VIOLATION); + } + file = smb_llist_next(&node->n_ofile_list, file); + } + smb_llist_exit(&node->n_ofile_list); + + /* + * system-wide share check + */ + + if (nbl_share_conflict(node->vp, NBL_REMOVE, NULL)) + return (NT_STATUS_SHARING_VIOLATION); + else + return (NT_STATUS_SUCCESS); +} + +/* + * smb_node_start_crit() + * + * Enter critical region for share reservations. + * See comments above smb_fsop_shrlock(). + */ + +void +smb_node_start_crit(smb_node_t *node, krw_t mode) +{ + rw_enter(&node->n_share_lock, mode); + nbl_start_crit(node->vp, mode); +} + +/* + * smb_node_end_crit() + * + * Exit critical region for share reservations. + */ + +void +smb_node_end_crit(smb_node_t *node) +{ + nbl_end_crit(node->vp); + rw_exit(&node->n_share_lock); +} + +int +smb_node_in_crit(smb_node_t *node) +{ + return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_share_lock)); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c index 36a3df5992..e7dbe26746 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -206,7 +206,7 @@ smb_com_nt_create_andx(struct smb_request *sr) } if (NameLength >= MAXPATHLEN) { - smbsr_raise_nt_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND); + smbsr_error(sr, NT_STATUS_OBJECT_PATH_NOT_FOUND, 0, 0); /* NOTREACHED */ } @@ -217,7 +217,7 @@ smb_com_nt_create_andx(struct smb_request *sr) if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } @@ -253,7 +253,7 @@ smb_com_nt_create_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -284,11 +284,10 @@ smb_com_nt_create_andx(struct smb_request *sr) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c index 00d648cc32..d844733b36 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -115,14 +115,14 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } if (sd_len) { status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } op->sd = &sd; @@ -177,11 +177,10 @@ smb_nt_transact_create(struct smb_request *sr, struct smb_xa *xa) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c index 5725814a0f..16fbdbede8 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -90,7 +90,7 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) &fid, &is_fsctl, &is_flags) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); } for (i = 0; @@ -103,7 +103,7 @@ smb_nt_transact_ioctl(struct smb_request *sr, struct smb_xa *xa) } if (status != NT_STATUS_SUCCESS) - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); (void) smb_encode_mbc(&xa->rep_param_mb, "l", 0); return (SDRC_NORMAL_REPLY); diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c index d70ddf4fc0..264a078a48 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -135,8 +135,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -144,10 +143,9 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) if (node->attr.sa_vattr.va_type != VDIR) { /* - * notify change requests are only valid for - * directories + * Notify change requests are only valid on directories. */ - smbsr_raise_nt_error(sr, NT_STATUS_NOT_A_DIRECTORY); + smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY, 0, 0); /* NOTREACHED */ } @@ -192,7 +190,7 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) case SMB_REQ_STATE_CANCELED: mutex_exit(&sr->sr_mutex); - smbsr_raise_nt_error(sr, NT_STATUS_CANCELLED); + smbsr_error(sr, NT_STATUS_CANCELLED, 0, 0); /* NOTREACHED */ default: ASSERT(0); @@ -211,13 +209,13 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa) * is sent in reply. */ int -smb_reply_notify_change_request( - smb_request_t *sr) +smb_reply_notify_change_request(smb_request_t *sr) { smb_node_t *node; int total_bytes, n_setup, n_param, n_data; int param_off, param_pad, data_off, data_pad; struct smb_xa *xa; + smb_error_t err; xa = sr->r_xa; node = sr->sr_ncr.nc_node; @@ -273,12 +271,12 @@ smb_reply_notify_change_request( break; case SMB_REQ_STATE_CANCELED: - /* - * an STATUS should be sent, - * we need an implementation of nt_raise_error - * but without long jump. - */ - smbsr_setup_nt_status(sr, 0xc0000000, NT_STATUS_CANCELLED); + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_CANCELLED; + err.errcls = ERRDOS; + err.errcode = ERROR_OPERATION_ABORTED; + smbsr_set_error(sr, &err); + (void) smb_encode_mbc(&sr->reply, "bwbw", (short)0, 0L, (short)0, 0L); sr->smb_wct = 0; diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c index fec95a2835..69ea40bdb3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_security.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -74,25 +74,24 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) uint32_t secinfo; uint32_t sdlen; uint32_t status; - + smb_error_t err; if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -107,14 +106,14 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_sd_read(sr, &sd, secinfo); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } sdlen = smb_sd_len(&sd, secinfo); if (sdlen == 0) { smb_sd_term(&sd); - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_SECURITY_DESCR); + smbsr_error(sr, NT_STATUS_INVALID_SECURITY_DESCR, 0, 0); /* NOTREACHED */ } @@ -126,8 +125,11 @@ smb_nt_transact_query_security_info(struct smb_request *sr, struct smb_xa *xa) * should provide a buffer size hint for the client. */ (void) smb_encode_mbc(&xa->rep_param_mb, "l", sdlen); - smbsr_setup_nt_status(sr, ERROR_SEVERITY_ERROR, - NT_STATUS_BUFFER_TOO_SMALL); + err.severity = ERROR_SEVERITY_ERROR; + err.status = NT_STATUS_BUFFER_TOO_SMALL; + err.errcls = ERRDOS; + err.errcode = ERROR_INSUFFICIENT_BUFFER; + smbsr_set_error(sr, &err); smb_sd_term(&sd); return (SDRC_NORMAL_REPLY); } @@ -166,25 +168,24 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) if (smb_decode_mbc(&xa->req_param_mb, "w2.l", &sr->smb_fid, &secinfo) != 0) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((sr->fid_ofile->f_node == NULL) || (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK)) { - smbsr_raise_nt_error(sr, NT_STATUS_ACCESS_DENIED); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, 0, 0); /* NOTREACHED */ } if (sr->fid_ofile->f_node->flags & NODE_READ_ONLY) { - smbsr_raise_nt_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED); + smbsr_error(sr, NT_STATUS_MEDIA_WRITE_PROTECTED, 0, 0); /* NOTREACHED */ } @@ -202,20 +203,20 @@ smb_nt_transact_set_security_info(struct smb_request *sr, struct smb_xa *xa) status = smb_decode_sd(xa, &sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } if (((secinfo & SMB_OWNER_SECINFO) && (sd.sd_owner == NULL)) || ((secinfo & SMB_GROUP_SECINFO) && (sd.sd_group == NULL))) { - smbsr_raise_nt_error(sr, NT_STATUS_INVALID_PARAMETER); + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0); /* NOTREACHED */ } status = smb_sd_write(sr, &sd, secinfo); smb_sd_term(&sd); if (status != NT_STATUS_SUCCESS) { - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c index e8eb106291..fa9631336b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c +++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -186,6 +186,7 @@ smb_ofile_open( uint16_t ftype, char *pipe_name, uint32_t rpc_fid, + uint32_t uniqid, smb_error_t *err) { smb_ofile_t *of; @@ -203,6 +204,7 @@ smb_ofile_open( of->f_magic = SMB_OFILE_MAGIC; of->f_refcnt = 1; of->f_fid = fid; + of->f_uniqid = uniqid; of->f_opened_by_pid = pid; of->f_granted_access = access_granted; of->f_share_access = share_access; @@ -271,7 +273,6 @@ smb_ofile_close( { int rc = 0; - ASSERT(of); ASSERT(of->f_magic == SMB_OFILE_MAGIC); @@ -286,9 +287,6 @@ smb_ofile_close( if (of->f_ftype == SMB_FTYPE_MESG_PIPE) { smb_rpc_close(of); } else { - if (of->f_node->vp->v_type == VREG) - (void) smb_fsop_close(of); - if (of->f_node->flags & NODE_CREATED_READONLY) { smb_node_set_dosattr(of->f_node, of->f_node->attr.sa_dosattr | @@ -300,12 +298,20 @@ smb_ofile_close( rc = smb_sync_fsattr(NULL, of->f_cr, of->f_node); smb_commit_delete_on_close(of); smb_release_oplock(of, OPLOCK_RELEASE_FILE_CLOSED); - smb_commit_delete_on_close(of); + + /* + * Share reservations cannot be removed until the + * readonly bit has been set (if needed), above. + * See comments in smb_open_subr(). + */ + smb_fsop_unshrlock(of->f_cr, of->f_node, of->f_uniqid); + + if (of->f_node->vp->v_type == VREG) + (void) smb_fsop_close(of); + /* - * if there is any notify change request for - * this file then see if any of them is related - * to this open instance. If there is any then - * cancel them. + * Cancel any notify change requests related + * to this open instance. */ if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE) smb_process_file_notify_change_queue(of); diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c index b195ed6353..486422d9c5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -245,7 +245,7 @@ smb_com_open(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -266,11 +266,10 @@ smb_com_open(struct smb_request *sr) if ((status = smb_open_subr(sr)) != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } @@ -281,7 +280,7 @@ smb_com_open(struct smb_request *sr) } if (op->dsize > UINT_MAX) - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); file_attr = op->dattr & FILE_ATTRIBUTE_MASK; @@ -330,7 +329,7 @@ smb_com_open_andx(struct smb_request *sr) if ((op->desired_access == ((uint32_t)SMB_INVALID_AMASK)) || (op->share_access == ((uint32_t)SMB_INVALID_SHAREMODE))) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_PARAMETER, + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -338,7 +337,7 @@ smb_com_open_andx(struct smb_request *sr) op->dattr = file_attr; op->create_disposition = smb_ofun_to_crdisposition(ofun); if (op->create_disposition == ((uint32_t)SMB_INVALID_CRDISPOSITION)) { - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_PARAMETER); + smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_PARAMETER); /* NOTREACHED */ } @@ -376,17 +375,16 @@ smb_com_open_andx(struct smb_request *sr) if (status != NT_STATUS_SUCCESS) { if (status == NT_STATUS_SHARING_VIOLATION) - smbsr_raise_cifs_error(sr, - NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); else - smbsr_raise_nt_error(sr, status); + smbsr_error(sr, status, 0, 0); /* NOTREACHED */ } if (op->dsize > UINT_MAX) - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); if (MYF_OPLOCK_TYPE(op->my_flags) != MYF_OPLOCK_NONE) { op->action_taken |= SMB_OACT_LOCK; diff --git a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c index cc203a7315..c31c764bf4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c +++ b/usr/src/uts/common/fs/smbsrv/smb_path_name_reduction.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -59,10 +59,6 @@ smb_is_executable(char *path) /* * smbd_fs_query * - * This function has been changed to return errors instead of using - * smbsr_raise_errno to longjmp round the calling code. This allows - * the caller to release resources when an error occurs. - * * Upon success, the caller will need to call smb_node_release() on * fqi.last_snode (if it isn't already set to NULL by this routine) and * and fqi.dir_snode. These pointers will not be used after the caller diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information.c b/usr/src/uts/common/fs/smbsrv/smb_query_information.c index 8cb636aaa9..391c3f9c24 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -95,7 +95,7 @@ smb_com_query_information(struct smb_request *sr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -103,7 +103,7 @@ smb_com_query_information(struct smb_request *sr) sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0)) != 0) { smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c index a1324aa74e..d6fa3d1f26 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information2.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -76,15 +76,13 @@ smb_com_query_information2(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if (sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { - cmn_err(CE_NOTE, "SmbQueryInfo2: access denied"); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c index 4c69d8516e..6e38758502 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_information_disk.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -79,7 +79,7 @@ smb_com_query_information_disk(struct smb_request *sr) if ((rc = smb_fsop_statfs(sr->user_cr, sr->tid_tree->t_snode, &df)) != 0) - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); unit_size = 1; block_size = df.f_frsize; diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c index 8542a1a1f9..4e5ba4ec88 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb_read.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -75,13 +75,12 @@ smb_com_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -123,7 +122,7 @@ smb_com_lock_and_read(struct smb_request *sr) int rc; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -139,19 +138,18 @@ smb_com_lock_and_read(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } result = smb_lock_range(sr, sr->fid_ofile, param.r_offset, (uint64_t)param.r_count, UINT_MAX, SMB_LOCK_TYPE_READWRITE); if (result != NT_STATUS_SUCCESS) { - smb_lock_range_raise_error(sr, result); + smb_lock_range_error(sr, result); } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -214,7 +212,7 @@ smb_com_read_raw(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -301,13 +299,12 @@ smb_com_read_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if ((rc = smb_common_read(sr, ¶m)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -379,7 +376,7 @@ smb_common_read(struct smb_request *sr, smb_read_param_t *param) if (node->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, node, param->r_offset, - param->r_count, FILE_READ_DATA); + param->r_count, B_FALSE); if (rc != NT_STATUS_SUCCESS) { rc = ERANGE; break; diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c index f22e7187de..0239635663 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rename.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -29,12 +29,12 @@ #include <sys/synch.h> #include <smbsrv/smb_incl.h> #include <smbsrv/smb_fsops.h> +#include <sys/nbmlock.h> static int smb_do_rename(struct smb_request *sr, struct smb_fqi *src_fqi, struct smb_fqi *dst_fqi); - /* * smb_com_rename * @@ -63,7 +63,7 @@ smb_com_rename(struct smb_request *sr) int rc; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -99,19 +99,18 @@ smb_com_rename(struct smb_request *sr) * NT and W2K client behaviour. */ if (rc == EEXIST) { - smbsr_raise_cifs_error(sr, - NT_STATUS_OBJECT_NAME_COLLISION, + smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION, ERRDOS, ERROR_ALREADY_EXISTS); /* NOTREACHED */ } if (rc == EPIPE) { - smbsr_raise_cifs_error(sr, NT_STATUS_SHARING_VIOLATION, + smbsr_error(sr, NT_STATUS_SHARING_VIOLATION, ERRDOS, ERROR_SHARING_VIOLATION); /* NOTREACHED */ } - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -136,48 +135,6 @@ smb_com_rename(struct smb_request *sr) } /* - * smb_rename_share_check - * - * An open file can be renamed if - * - * 1. isn't opened for data writing or deleting - * - * 2. Opened with "Deny Delete" share mode - * But not opened for data reading or executing - * (opened for accessing meta data) - */ -DWORD -smb_rename_share_check(struct smb_node *node) -{ - struct smb_ofile *open; - - if (node == 0 || node->n_refcnt <= 1) - return (NT_STATUS_SUCCESS); - - smb_llist_enter(&node->n_ofile_list, RW_READER); - open = smb_llist_head(&node->n_ofile_list); - while (open) { - if (open->f_granted_access & - (FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - - if ((open->f_share_access & FILE_SHARE_DELETE) == 0) { - if (open->f_granted_access & - (FILE_READ_DATA | FILE_EXECUTE)) { - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SHARING_VIOLATION); - } - } - open = smb_llist_next(&node->n_ofile_list, open); - } - smb_llist_exit(&node->n_ofile_list); - return (NT_STATUS_SUCCESS); -} - - -/* * smb_do_rename * * Backend to smb_com_rename to ensure that the rename operation is atomic. @@ -228,28 +185,24 @@ smb_do_rename( } } - status = smb_lock_range_access(sr, src_node, 0, 0, FILE_WRITE_DATA); - if (status != NT_STATUS_SUCCESS) { - smb_node_release(src_node); - smb_node_release(src_fqi->dir_snode); + for (count = 0; count <= 3; count++) { + if (count) { + smb_node_end_crit(src_node); + delay(MSEC_TO_TICK(400)); + } - SMB_NULL_FQI_NODES(*src_fqi); - SMB_NULL_FQI_NODES(*dst_fqi); - return (EACCES); - } + smb_node_start_crit(src_node, RW_READER); + status = smb_node_rename_check(src_node); - for (count = 0; count <= 3; count++) { - if (count) - delay(MSEC_TO_TICK(400)); - status = smb_rename_share_check(src_node); if (status != NT_STATUS_SHARING_VIOLATION) break; } - smb_node_release(src_node); - if (status == NT_STATUS_SHARING_VIOLATION) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -257,8 +210,25 @@ smb_do_rename( return (EPIPE); /* = ERRbadshare */ } + status = smb_range_check(sr, sr->user_cr, src_node, 0, UINT64_MAX, + B_TRUE); + + if (status != NT_STATUS_SUCCESS) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); + smb_node_release(src_fqi->dir_snode); + + SMB_NULL_FQI_NODES(*src_fqi); + SMB_NULL_FQI_NODES(*dst_fqi); + return (EACCES); + } + if (utf8_strcasecmp(src_fqi->path, dst_fqi->path) == 0) { if ((rc = smbd_fs_query(sr, dst_fqi, 0)) != 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -276,6 +246,9 @@ smb_do_rename( rc = strcmp(src_fqi->last_comp_od, dst_fqi->last_comp); if (rc == 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); smb_node_release(dst_fqi->dir_snode); @@ -297,11 +270,18 @@ smb_do_rename( SMB_NULL_FQI_NODES(*src_fqi); SMB_NULL_FQI_NODES(*dst_fqi); } + + smb_node_end_crit(src_node); + + smb_node_release(src_node); return (rc); } rc = smbd_fs_query(sr, dst_fqi, FQM_PATH_MUST_NOT_EXIST); if (rc != 0) { + smb_node_end_crit(src_node); + + smb_node_release(src_node); smb_node_release(src_fqi->dir_snode); SMB_NULL_FQI_NODES(*src_fqi); @@ -343,5 +323,9 @@ smb_do_rename( SMB_NULL_FQI_NODES(*dst_fqi); } + smb_node_end_crit(src_node); + + smb_node_release(src_node); + return (rc); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_rpc.c b/usr/src/uts/common/fs/smbsrv/smb_rpc.c index 5059c909b4..a270f442b1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rpc.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rpc.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -205,7 +205,8 @@ smb_rpc_initialize(struct smb_request *sr, char *pipe_name) op = &sr->arg.open; of = smb_ofile_open(sr->tid_tree, NULL, sr->smb_pid, op->desired_access, 0, op->share_access, - SMB_FTYPE_MESG_PIPE, pipe_name, smb_rpc_fid(), &err); + SMB_FTYPE_MESG_PIPE, pipe_name, smb_rpc_fid(), + SMB_UNIQ_FID(), &err); if (of == NULL) return (err.status); @@ -267,7 +268,7 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) if (pipe_info->fid == 0) { smb_rpc_exit(pipe_info); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERROR_INVALID_HANDLE); /* NOTREACHED */ } @@ -286,8 +287,8 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) if (rc != 0) { smb_rpc_exit(pipe_info); - smbsr_raise_nt_error(sr, - NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID); + smbsr_error(sr, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID, + 0, 0); /* NOTREACHED */ } @@ -310,13 +311,8 @@ smb_rpc_transact(struct smb_request *sr, struct uio *uio) xa->rep_data_mb.max_bytes = mdrcnt; MBC_ATTACH_MBUF(&xa->rep_data_mb, mhead); - if (sr->session->capabilities & CAP_STATUS32) - smbsr_setup_nt_status(sr, ERROR_SEVERITY_WARNING, - NT_STATUS_BUFFER_OVERFLOW); - else { - sr->smb_rcls = ERRDOS; - sr->smb_err = ERRmoredata; - } + smbsr_warn(sr, NT_STATUS_BUFFER_OVERFLOW, + ERRDOS, ERROR_MORE_DATA); } else { /* * The client has provided enough buffer space, all diff --git a/usr/src/uts/common/fs/smbsrv/smb_sd.c b/usr/src/uts/common/fs/smbsrv/smb_sd.c index fa2bf223d7..c26b70169a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_sd.c +++ b/usr/src/uts/common/fs/smbsrv/smb_sd.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -145,7 +145,7 @@ smb_sd_read(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) error = smb_fsop_sdread(sr, sr->user_cr, node, &fs_sd); if (error) { - smb_errmap_unix2smb(error, &smb_err); + smbsr_map_errno(error, &smb_err); return (smb_err.status); } @@ -186,7 +186,7 @@ smb_sd_write(smb_request_t *sr, smb_sd_t *sd, uint32_t secinfo) smb_fssd_term(&fs_sd); if (error) { - smb_errmap_unix2smb(error, &smb_err); + smbsr_map_errno(error, &smb_err); return (smb_err.status); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_search.c b/usr/src/uts/common/fs/smbsrv/smb_search.c index 0700b8fd2d..d0411e1e58 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_search.c +++ b/usr/src/uts/common/fs/smbsrv/smb_search.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -162,7 +162,7 @@ smb_com_search(struct smb_request *sr) } if ((rc = fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -212,8 +212,7 @@ smb_com_search(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, - NT_STATUS_INVALID_HANDLE, + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -270,13 +269,13 @@ smb_com_search(struct smb_request *sr) if ((rc != 0) && (rc != ENOENT)) { /* returned error by smb_rdir_next() */ smb_rdir_close(sr); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if (count == 0) { smb_rdir_close(sr); - smbsr_raise_error(sr, ERRDOS, ERRnofiles); + smbsr_error(sr, 0, ERRDOS, ERRnofiles); /* NOTREACHED */ } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_seek.c b/usr/src/uts/common/fs/smbsrv/smb_seek.c index a120a26a9d..cffb9ce2d0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_seek.c +++ b/usr/src/uts/common/fs/smbsrv/smb_seek.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -94,8 +94,7 @@ smb_com_seek(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -103,27 +102,16 @@ smb_com_seek(struct smb_request *sr) (void) smb_set_file_size(sr); } - rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret); - if (rc == 0) { - smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0); - return (SDRC_NORMAL_REPLY); + if ((rc = smb_ofile_seek(sr->fid_ofile, mode, off, &off_ret)) != 0) { + if (rc == EINVAL) { + smbsr_error(sr, 0, ERRDOS, ERRbadfunc); + /* NOTREACHED */ + } else { + smbsr_error(sr, 0, ERRSRV, ERRerror); + /* NOTREACHED */ + } } - if (rc == EINVAL) { - smbsr_raise_error(sr, ERRDOS, ERRbadfunc); - /* NOTREACHED */ - } - if (rc == EOVERFLOW) { - smbsr_raise_error(sr, ERRSRV, ERRerror); - /* NOTREACHED */ - } - ASSERT(0); - smbsr_raise_error(sr, ERRSRV, ERRerror); - /* NOTREACHED */ - /* - * Although smbsr_raise_error() doesn't return and the compiler is - * told so in smb_kproto.h it still has a problem if it doesn't - * find here a return instruction with a value. - */ - return (0); + smbsr_encode_result(sr, 2, 0, "blw", 2, off_ret, 0); + return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c index b7217cf78b..887a0ca648 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -370,7 +370,7 @@ smb_com_session_setup_andx(struct smb_request *sr) kmem_free(ci_password, ci_pwlen + 1); if (cs_password) kmem_free(cs_password, cs_pwlen + 1); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ } else if (utf8_strcasecmp(primary_domain, hostname) == 0) { /* @@ -385,8 +385,6 @@ smb_com_session_setup_andx(struct smb_request *sr) clnt_info.flags |= NETR_CFLG_LOCAL; } - (void) utf8_strupr(primary_domain); - /* * If this is an additional setup for an existing user * on this session, duplicate the authenticated user. @@ -431,7 +429,7 @@ smb_com_session_setup_andx(struct smb_request *sr) kmem_free(ci_password, ci_pwlen + 1); if (cs_password) kmem_free(cs_password, cs_pwlen + 1); - smbsr_raise_error(sr, ERRSRV, ERRbadpw); + smbsr_error(sr, 0, ERRSRV, ERRbadpw); /* NOTREACHED */ } @@ -463,7 +461,7 @@ smb_com_session_setup_andx(struct smb_request *sr) if (user == NULL) { if (session_key) kmem_free(session_key, sizeof (smb_session_key_t)); - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_HANDLE); + smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); /* no return */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_set_information.c index 728c86b8cd..e7b1237fa9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -88,7 +88,7 @@ smb_com_set_information(struct smb_request *sr) sr->tid_tree->t_snode, sr->tid_tree->t_snode, &dir_node, name)) != 0) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -96,7 +96,7 @@ smb_com_set_information(struct smb_request *sr) sr->tid_tree->t_snode, dir_node, name, &node, &attr, 0, 0)) != 0) { smb_node_release(dir_node); kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -118,7 +118,7 @@ smb_com_set_information(struct smb_request *sr) smb_node_release(node); if (rc) { kmem_free(name, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c index 1510f7228a..8f00ff66d1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_information2.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_information2.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -77,16 +77,14 @@ smb_com_set_information2(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } node = sr->fid_ofile->f_node; if (node == 0 || sr->fid_ofile->f_ftype != SMB_FTYPE_DISK) { - cmn_err(CE_NOTE, "SmbSetInfo2: access denied"); - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -113,7 +111,7 @@ smb_com_set_information2(struct smb_request *sr) smb_node_set_time(node, &crtime, &mtime, &atime, 0, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c index 6ef6691df3..dc85916d04 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_create_directory.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -67,8 +67,8 @@ extern int smb_common_create_directory(struct smb_request *sr); int smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa) { - int rc; - DWORD status; + int rc; + DWORD status; if (smb_decode_mbc(&xa->req_param_mb, "%4.s", sr, &sr->arg.dirop.fqi.path) != 0) { @@ -77,16 +77,12 @@ smb_com_trans2_create_directory(struct smb_request *sr, struct smb_xa *xa) } if ((status = smb_validate_dirname(sr->arg.dirop.fqi.path)) != 0) { - if (sr->session->capabilities & CAP_STATUS32) - smbsr_raise_nt_error(sr, status); - else - smbsr_raise_error(sr, ERRDOS, ERROR_INVALID_NAME); - + smbsr_error(sr, status, ERRDOS, ERROR_INVALID_NAME); /* NOTREACHED */ } if ((rc = smb_common_create_directory(sr)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c index c92a248a93..57b3ba257c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -176,36 +176,50 @@ #include <smbsrv/smbtrans.h> #include <smbsrv/smb_fsops.h> -int smb_trans2_find_get_maxdata(struct smb_request *, unsigned short, - unsigned short); +static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t); -int smb_trans2_find_get_dents(struct smb_request *, struct smb_xa *, - unsigned short, unsigned short, int, struct smb_node *, - unsigned short, uint32_t, int, char *, uint32_t *, int *, int *); +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 *, struct smb_node *, char *, char *); + smb_attr_t *, smb_node_t *, char *, char *); -int smb_trans2_find_process_ients(struct smb_request *, struct smb_xa *, - smb_dent_info_hdr_t *, unsigned short, unsigned short, int, - struct smb_node *, int *, uint32_t *); +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(struct smb_request *, struct smb_xa *, - smb_dent_info_t *, int, unsigned short, unsigned short, - unsigned int, struct smb_node *, struct smb_node *); +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 *); /* - * Support for Catia Version 5 Deployment + * 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)(unsigned char *, unsigned char *, int) = NULL; +static int (*catia_callback)(uint8_t *, uint8_t *, int) = NULL; void smb_register_catia_callback( - int (*catia_v4tov5)(unsigned char *, unsigned char *, int)); + int (*catia_v4tov5)(uint8_t *, uint8_t *, int)); void smb_unregister_catia_callback(); /* - * Patchable parameter for find maximum count + * Tunable parameter to limit the maximum + * number of entries to be returned. */ -int max_find_count = 64; +uint16_t smb_trans2_find_max = 128; /* * smb_register_catia_callback @@ -216,7 +230,7 @@ int max_find_count = 64; */ void smb_register_catia_callback( - int (*catia_v4tov5)(unsigned char *, unsigned char *, int)) + int (*catia_v4tov5)(uint8_t *, uint8_t *, int)) { catia_callback = catia_v4tov5; } @@ -277,20 +291,21 @@ smb_unregister_catia_callback() * found in the search */ int -smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) +smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) { int more = 0, rc; - unsigned short sattr, fflag, infolev; + uint16_t sattr, fflag, infolev; + uint16_t maxcount = 0; int maxdata; - int count, maxcount = 0, wildcards; + int count, wildcards; uint32_t cookie; char *path; - struct smb_node *dir_snode; + smb_node_t *dir_snode; char *pattern; - unsigned short sid; + uint16_t sid; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -302,27 +317,36 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) } maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); - if (maxdata == 0) { - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, NT_STATUS_INVALID_LEVEL, + ERRDOS, ERROR_INVALID_LEVEL); /* NOTREACHED */ } - /* Convert name to our form */ - if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) { + /* + * 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); - } + (void) smb_rdir_open(sr, path, sattr); /* * Get a copy of information */ - pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); dir_snode = sr->sid_odir->d_dir_snode; + pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); (void) strcpy(pattern, sr->sid_odir->d_pattern); - /* this is funky */ + if (strcmp(pattern, "*.*") == 0) (void) strncpy(pattern, "*", sizeof (pattern)); + wildcards = sr->sid_odir->d_wildcards; sattr = sr->sid_odir->d_sattr; cookie = 0; @@ -337,23 +361,22 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) if (rc) { smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } /* - * Save the sid here because search might get closed - * and sr->smb_sid becomes invalid. - * This might not seem important because the search - * is going to be finished anyways, but it's just for - * the sake of compatibility with Windows. + * 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)) + (!more && fflag & SMB_FIND_CLOSE_AT_EOS)) { smb_rdir_close(sr); - else { + } else { mutex_enter(&sr->sid_odir->d_mutex); sr->sid_odir->d_cookie = cookie; mutex_exit(&sr->sid_odir->d_mutex); @@ -366,8 +389,6 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } - - /* * smb_com_trans2_find_next2 * @@ -418,57 +439,61 @@ smb_com_trans2_find_first2(struct smb_request *sr, struct smb_xa *xa) * matches found in the search */ int -smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) +smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) { - unsigned short fflag, infolev; + uint16_t fflag, infolev; int maxdata, count, wildcards, more = 0, rc; uint32_t cookie; - uint32_t maxcount = 0; - struct smb_node *dir_snode; + uint16_t maxcount = 0; + smb_node_t *dir_snode; char *pattern; - unsigned short sattr; + uint16_t sattr; - pattern = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* - * There is a path field as the last piece of input information: + * The last parameter in the request is a path, which is a + * null-terminated unicode string. * * smb_decode_mbc(&xa->req_param_mb, "%www lwu", sr, - * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &path) + * &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag, &path) * - * This feild has been removed because it's causing problem - * with Mac OS 10 and it's not used anyways. - * The problem is that code expects to see a 2-byte null - * because the strings are supposed to be Unicode, but - * Max OS 10 sends a 1-byte null which leads to decode error. + * We don't reference this parameter and it is not currently + * decoded because we a expect 2-byte null but Mac OS 10 + * clients send a 1-byte null, which leads to a decode error. */ if (smb_decode_mbc(&xa->req_param_mb, "%www lw", sr, &sr->smb_sid, &maxcount, &infolev, &cookie, &fflag) != 0) { - kmem_free(pattern, MAXNAMELEN); smbsr_decode_error(sr); /* NOTREACHED */ } - maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); - sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - kmem_free(pattern, MAXNAMELEN); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } + maxdata = smb_trans2_find_get_maxdata(sr, infolev, fflag); if (maxdata == 0) { smb_rdir_close(sr); - kmem_free(pattern, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, NT_STATUS_INVALID_LEVEL, + ERRDOS, ERROR_INVALID_LEVEL); /* NOTREACHED */ } /* + * 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; + + /* * 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; @@ -478,17 +503,6 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) mutex_exit(&sr->sid_odir->d_mutex); } - /* - * XXX this is an optimization made for SFS2 filesystem, it might - * not be required for ZFS - * - * Break the count to smaller counts (less than the default 150) - * to reduce the number of transaction failures - * which may cause excessive delays and eventually a SMB staled - * connection. - */ - maxcount = (maxcount > max_find_count) ? max_find_count : maxcount; - rc = smb_trans2_find_get_dents(sr, xa, fflag, infolev, maxdata, dir_snode, sattr, maxcount, wildcards, pattern, &cookie, &more, &count); @@ -496,7 +510,7 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) if (rc) { smb_rdir_close(sr); kmem_free(pattern, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -516,21 +530,17 @@ smb_com_trans2_find_next2(struct smb_request *sr, struct smb_xa *xa) return (SDRC_NORMAL_REPLY); } - /* * smb_trans2_find_get_maxdata * - * This function calculates the minimum space requirement for the - * base on information level and fflag. + * Calculate the minimum response space required for the specified + * information level. * - * When success, minimum space requirement will be returned; otherwise, - * 0 will be returned. + * A non-zero return value provides the minimum space required. + * A return value of zero indicates an unknown information level. */ -int -smb_trans2_find_get_maxdata( - struct smb_request *sr, - unsigned short infolev, - unsigned short fflag) +static int +smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag) { int maxdata; @@ -573,8 +583,6 @@ smb_trans2_find_get_maxdata( return (maxdata); } - - /* * smb_trans2_find_get_dents * @@ -591,12 +599,12 @@ smb_trans2_find_get_maxdata( int smb_trans2_find_get_dents( smb_request_t *sr, smb_xa_t *xa, - unsigned short fflag, - unsigned short infolev, + uint16_t fflag, + uint16_t infolev, int maxdata, smb_node_t *dir_snode, - unsigned short sattr, - uint32_t maxcount, + uint16_t sattr, + uint16_t maxcount, int wildcards, char *pattern, uint32_t *cookie, @@ -686,7 +694,7 @@ int smb_get_dents( smb_request_t *sr, uint32_t *cookie, smb_node_t *dir_snode, - unsigned int wildcards, + uint32_t wildcards, smb_dent_info_hdr_t *ihdr, int *more) { @@ -787,8 +795,8 @@ smb_gather_dents_info( /*LINTED E_BAD_PTR_CAST_ALIGN*/ smb_dent_info_hdr_t *ihdr = (smb_dent_info_hdr_t *)args; smb_dent_info_t *ient; - unsigned char *v5_name = NULL; - unsigned char *np = (unsigned char *)name; + 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); @@ -805,28 +813,8 @@ smb_gather_dents_info( return (0); } - /* - * If StorEdge is configured to support Catia Version 5 deployments, - * any directory entry whose name contains the special Unix character - * that is considered to be illegal in Windows environement will be - * translated based on the following - * Special Character Translation Table. - * - * --------------------------- - * 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 - */ if (catia_callback) { - /* XXX 255 should be max name len or something */ - catia_callback(v5_name, (unsigned char *)name, 255); + catia_callback(v5_name, (uint8_t *)name, MAXNAMELEN-1); np = v5_name; reclen = sizeof (smb_dent_info_t) + strlen((char *)v5_name); } @@ -876,15 +864,15 @@ smb_gather_dents_info( */ int smb_trans2_find_process_ients( - struct smb_request *sr, - struct smb_xa *xa, - smb_dent_info_hdr_t *ihdr, - unsigned short fflag, - unsigned short infolev, - int maxdata, - struct smb_node *dir_snode, - int *more, - uint32_t *cookie) + 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; @@ -897,15 +885,15 @@ smb_trans2_find_process_ients( break; /* - * FYI: Some observed differences between our response and - * Windows response which hasn't caused problem yet! + * 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 put the - * result in this field. + * 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 put the cookie - * in this 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); @@ -915,8 +903,8 @@ smb_trans2_find_process_ients( } /* - * Not enough space to store all the entries returned; therefore, - * update the more to 1. + * Not enough space to store all the entries returned, + * which is indicated by setting more. */ if (more && err < 0) { *more = 1; @@ -931,8 +919,6 @@ smb_trans2_find_process_ients( return (i); } - - /* * smb_trans2_find_mbc_encode * @@ -942,45 +928,45 @@ smb_trans2_find_process_ients( * is reached. If the entry is valid and successful encoded, 0 * will be returned; otherwise, 1 will be returned. */ -int smb_trans2_find_mbc_encode( - struct smb_request *sr, - struct smb_xa *xa, - smb_dent_info_t *ient, - int maxdata, - unsigned short infolev, - unsigned short fflag, - unsigned int mb_flags, - struct smb_node *dir_snode, /*LINTED E_FUNC_ARG_UNUSED*/ - struct smb_node *sd_snode) +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) { int uni_namelen; - int sl, rl; + int shortlen; + uint32_t next_entry_offset; char buf83[26]; smb_msgbuf_t mb; uint32_t dattr = 0; uint32_t size32 = 0; uint64_t size64 = 0; - struct smb_node *lnk_snode; + smb_node_t *lnk_snode; smb_attr_t lnkattr; int rc; uni_namelen = smb_ascii_or_unicode_strlen(sr, ient->name); - if (uni_namelen == -1) return (1); + next_entry_offset = maxdata + uni_namelen; + if (MBC_ROOM_FOR(&xa->rep_data_mb, (maxdata + uni_namelen)) == 0) return (-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); /* - * IR 104598 - * * 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 @@ -990,7 +976,7 @@ int smb_trans2_find_mbc_encode( * 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. - * So we've added a flag that allows an end-user to disable + * skc_dirsymlink_enable allows an end-user to disable * symlinks to directories. Symlinks to other object types * should be unaffected. */ @@ -1012,10 +998,6 @@ int smb_trans2_find_mbc_encode( dattr = smb_mode_to_dos_attributes(&ient->attr); } - /* - * we don't send the '.stream' to client. User shouldn't - * see this directory. - */ switch (infolev) { case SMB_INFO_STANDARD: if (fflag & SMB_FIND_RETURN_RESUME_KEYS) @@ -1036,8 +1018,8 @@ int smb_trans2_find_mbc_encode( case SMB_INFO_QUERY_EA_SIZE: if (fflag & SMB_FIND_RETURN_RESUME_KEYS) - (void) smb_encode_mbc(&xa->rep_data_mb, - "l", ient->cookie); + (void) smb_encode_mbc(&xa->rep_data_mb, "l", + ient->cookie); (void) smb_encode_mbc(&xa->rep_data_mb, "%yyyllwlbu", sr, ient->attr.sa_crtime.tv_sec ? ient->attr.sa_crtime.tv_sec : @@ -1053,11 +1035,8 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_DIRECTORY_INFO: - /* Use maxdata instead */ - rl = maxdata + uni_namelen; - (void) smb_encode_mbc(&xa->rep_data_mb, "%llTTTTqqllu", sr, - rl, + next_entry_offset, ient->cookie, ient->attr.sa_crtime.tv_sec ? &ient->attr.sa_crtime : &ient->attr.sa_vattr.va_mtime, @@ -1072,20 +1051,18 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - /* Use maxdata instead */ - rl = maxdata + uni_namelen; bzero(buf83, sizeof (buf83)); - smb_msgbuf_init(&mb, (unsigned char *)buf83, sizeof (buf83), + smb_msgbuf_init(&mb, (uint8_t *)buf83, sizeof (buf83), mb_flags); if (smb_msgbuf_encode(&mb, "u", ient->shortname) < 0) { smb_msgbuf_term(&mb); return (-1); } - sl = smb_ascii_or_unicode_strlen(sr, ient->shortname); + shortlen = smb_ascii_or_unicode_strlen(sr, ient->shortname); - (void) smb_encode_mbc(&xa->rep_data_mb, - "%llTTTTqqlllb.24cu", sr, - rl, + (void) smb_encode_mbc(&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, @@ -1097,7 +1074,7 @@ int smb_trans2_find_mbc_encode( dattr, uni_namelen, 0L, - sl, + shortlen, buf83, ient->name); @@ -1105,9 +1082,8 @@ int smb_trans2_find_mbc_encode( break; case SMB_FIND_FILE_NAMES_INFO: - rl = maxdata + uni_namelen; (void) smb_encode_mbc(&xa->rep_data_mb, "%lllu", sr, - rl, + next_entry_offset, ient->cookie, uni_namelen, ient->name); @@ -1121,7 +1097,7 @@ int smb_trans2_find_mbc_encode( * Close a search started by a Trans2FindFirst2 request. */ int -smb_com_find_close2(struct smb_request *sr) +smb_com_find_close2(smb_request_t *sr) { if (smbsr_decode_vwv(sr, "w", &sr->smb_sid) != 0) { smbsr_decode_error(sr); @@ -1130,13 +1106,11 @@ smb_com_find_close2(struct smb_request *sr) sr->sid_odir = smb_odir_lookup_by_sid(sr->tid_tree, sr->smb_sid); if (sr->sid_odir == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } smb_rdir_close(sr); - smbsr_encode_empty_result(sr); return (SDRC_NORMAL_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c index e6d4dbeccf..d4b5443cd9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_file_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -105,8 +105,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -176,7 +175,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) break; default: - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOTREACHED */ break; } @@ -359,7 +358,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) if (dir_snode == NULL) { kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRbadfile); + smbsr_error(sr, 0, ERRDOS, ERRbadfile); /* NOT REACHED */ } (void) smb_encode_mbc(&xa->rep_param_mb, "w", 0); @@ -386,7 +385,7 @@ smb_com_trans2_query_file_information(struct smb_request *sr, struct smb_xa *xa) default: kmem_free(filebuf, MAXNAMELEN+1); kmem_free(mangled_name, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c index 509c4094f0..a1820b899e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_fs_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -283,14 +283,14 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) snode = sr->tid_tree->t_snode; if (fsd_getattr(&sr->tid_tree->t_fsd, &vol_attr) != 0) { - smbsr_raise_errno(sr, ESTALE); + smbsr_errno(sr, ESTALE); /* NOTREACHED */ } switch (infolev) { case SMB_INFO_ALLOCATION: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -365,7 +365,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) case SMB_QUERY_FS_SIZE_INFO: if ((rc = smb_fsop_statfs(sr->user_cr, snode, &df)) != 0) { - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -425,7 +425,7 @@ smb_com_trans2_query_fs_information(struct smb_request *sr, struct smb_xa *xa) break; default: - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c index 374a6de2bd..bea67e6545 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_query_path_info.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -341,7 +341,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) int len; if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -382,7 +382,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -393,7 +393,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } smb_node_release(dir_node); @@ -576,7 +576,7 @@ smb_com_trans2_query_path_information(struct smb_request *sr, struct smb_xa *xa) kmem_free(name, MAXNAMELEN); kmem_free(short_name, MAXNAMELEN); kmem_free(name83, MAXNAMELEN); - smbsr_raise_error(sr, ERRDOS, ERRunknownlevel); + smbsr_error(sr, 0, ERRDOS, ERRunknownlevel); /* NOTREACHED */ break; } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c index 094032da1c..de71abb6d3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_file_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -123,7 +123,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || SMB_TREE_IS_READ_ONLY(sr)) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -131,8 +131,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -142,7 +141,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) !SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) { cmn_err(CE_NOTE, "SmbT2SetFileInfo: access denied"); kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -154,8 +153,7 @@ smb_com_trans2_set_file_information(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } else if (status == NT_STATUS_UNSUCCESSFUL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, smberr.status, - smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ } kmem_free(info, sizeof (smb_trans2_setinfo_t)); diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c index 8c4368f93f..782e42f36d 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -228,7 +228,7 @@ smb_set_standard_info( smb_node_set_time(node, &crtime, &mtime, &atime, 0, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } @@ -295,7 +295,7 @@ smb_set_basic_info( smb_node_set_time(node, &crtime, &mtime, &atime, &ctime, what); rc = smb_sync_fsattr(sr, sr->user_cr, node); if (rc) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } @@ -339,7 +339,7 @@ smb_set_alloc_info( * write requests without the inode ever being updated. */ if ((rc = smb_set_file_size(sr)) != 0) { - smb_errmap_unix2smb(rc, smberr); + smbsr_map_errno(rc, smberr); status = NT_STATUS_UNSUCCESSFUL; } } diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c index 02be8c53cb..fd3c2d571f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_set_path_information.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -134,7 +134,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (!STYPE_ISDSK(sr->tid_tree->t_res_type) || SMB_TREE_IS_READ_ONLY(sr)) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); /* NOTREACHED */ } @@ -145,7 +145,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -157,7 +157,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) if (rc != 0) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); } info->node = ret_snode; @@ -170,8 +170,7 @@ smb_com_trans2_set_path_information(struct smb_request *sr, struct smb_xa *xa) /* NOTREACHED */ } else if (status == NT_STATUS_UNSUCCESSFUL) { kmem_free(info, sizeof (smb_trans2_setinfo_t)); - smbsr_raise_cifs_error(sr, smberr.status, - smberr.errcls, smberr.errcode); + smbsr_error(sr, smberr.status, smberr.errcls, smberr.errcode); /* NOTREACHED */ } kmem_free(info, sizeof (smb_trans2_setinfo_t)); diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c index 9139930a4d..560c1d7b76 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_disconnect.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -100,9 +100,10 @@ smb_com_tree_disconnect(struct smb_request *sr) sr->smb_tid); if (sr->uid_user == NULL || sr->tid_tree == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRinvnid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid); + /* NOTREACHED */ } + smbsr_rq_notify(sr, sr->session, sr->tid_tree); smb_tree_disconnect(sr->tid_tree); smbsr_encode_empty_result(sr); diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c index fef432d9fc..8e75fadc36 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,15 +69,15 @@ smb_com_unlock_byte_range(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } result = smb_unlock_range(sr, sr->fid_ofile->f_node, (u_offset_t)Offset, (uint64_t)Length); if (result != NT_STATUS_SUCCESS) { - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOT REACHED */ } diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c index 538c9cfc91..0e9bbe45f2 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_vops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,9 @@ #include <sys/pathname.h> #include <sys/cred.h> #include <sys/extdirent.h> +#include <sys/nbmlock.h> +#include <sys/share.h> +#include <sys/fcntl.h> #include <smbsrv/smb_vops.h> #include <smbsrv/string.h> @@ -43,21 +46,22 @@ #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 *vp, void *buf, uint32_t offset, int *count, - cred_t *cr, caller_context_t *ct, int flags); + cred_t *cr, int flags); 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, - caller_context_t *ct, char *dirbuf, int num_bytes); + char *dirbuf, int num_bytes); static int smb_vop_getdents_entries(smb_node_t *dir_snode, uint32_t *cookiep, int32_t *dircountp, char *arg, uint32_t flags, struct smb_request *sr, - cred_t *cr, caller_context_t *ct, char *dirbuf, int *maxentries, - int num_bytes, char *); + cred_t *cr, char *dirbuf, int *maxentries, int num_bytes, char *); extern int smb_gather_dents_info(char *args, ino_t fileid, int namelen, @@ -68,6 +72,8 @@ smb_gather_dents_info(char *args, ino_t fileid, int namelen, static void smb_sa_to_va_mask(uint_t sa_mask, uint_t *va_maskp); +extern sysid_t lm_alloc_sysidt(); + #define SMB_AT_MAX 16 static uint_t smb_attrmap[SMB_AT_MAX] = { 0, @@ -88,16 +94,45 @@ static uint_t smb_attrmap[SMB_AT_MAX] = { AT_SEQ }; +/* + * The smb_ct will be used primarily for range locking. + * Since the CIFS server is mapping its locks to POSIX locks, + * only one pid is used for operations originating from the + * CIFS server (to represent CIFS in the VOP_FRLOCK routines). + */ + +caller_context_t smb_ct; + +/* + * smb_vop_start() + * + * Initialize the smb caller context. This function must be called + * before any other smb_vop calls. + */ + +void +smb_vop_start(void) +{ + static boolean_t initialized = B_FALSE; + + if (!initialized) { + smb_ct.cc_caller_id = fs_new_caller_id(); + smb_ct.cc_pid = ttoproc(curthread)->p_pid; + smb_ct.cc_sysid = lm_alloc_sysidt(); + initialized = B_TRUE; + } +} + int -smb_vop_open(vnode_t **vpp, int mode, cred_t *cred, caller_context_t *ct) +smb_vop_open(vnode_t **vpp, int mode, cred_t *cred) { - return (VOP_OPEN(vpp, mode, cred, ct)); + return (VOP_OPEN(vpp, mode, cred, &smb_ct)); } int -smb_vop_close(vnode_t *vp, int mode, cred_t *cred, caller_context_t *ct) +smb_vop_close(vnode_t *vp, int mode, cred_t *cred) { - return (VOP_CLOSE(vp, mode, 1, (offset_t)0, cred, ct)); + return (VOP_CLOSE(vp, mode, 1, (offset_t)0, cred, &smb_ct)); } /* @@ -115,19 +150,19 @@ smb_vop_close(vnode_t *vp, int mode, cred_t *cred, caller_context_t *ct) */ int -smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr, caller_context_t *ct) +smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr) { int error; (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); - error = VOP_READ(vp, uiop, 0, cr, ct); + error = VOP_READ(vp, uiop, 0, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); return (error); } int smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; int ioflag = 0; @@ -140,7 +175,7 @@ smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, uiop->uio_llimit = MAXOFFSET_T; (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); - error = VOP_WRITE(vp, uiop, ioflag, cr, ct); + error = VOP_WRITE(vp, uiop, ioflag, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); *lcount -= uiop->uio_resid; @@ -168,7 +203,7 @@ smb_vop_write(vnode_t *vp, uio_t *uiop, uint32_t *flag, uint32_t *lcount, int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, - int flags, cred_t *cr, caller_context_t *ct) + int flags, cred_t *cr) { int error; vnode_t *use_vp; @@ -197,7 +232,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); if ((error = VOP_GETATTR(use_vp, (vattr_t *)&tmp_xvattr, flags, - cr, ct)) != 0) + cr, &smb_ct)) != 0) return (error); ret_attr->sa_vattr = tmp_xvattr.xva_vattr; @@ -250,7 +285,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, tmp_xvattr.xva_vattr.va_mask = AT_SIZE; if ((error = VOP_GETATTR(vp, (vattr_t *)&tmp_xvattr, - flags, cr, ct)) != 0) + flags, cr, &smb_ct)) != 0) return (error); ret_attr->sa_vattr.va_size = @@ -272,7 +307,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, 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, ct); + error = VOP_GETATTR(use_vp, &ret_attr->sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); @@ -297,7 +332,7 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, */ tmp_attr.sa_vattr.va_mask = AT_SIZE; - error = VOP_GETATTR(vp, &tmp_attr.sa_vattr, flags, cr, ct); + error = VOP_GETATTR(vp, &tmp_attr.sa_vattr, flags, cr, &smb_ct); if (error != 0) return (error); @@ -326,14 +361,13 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr, int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, - int flags, cred_t *cr, boolean_t no_xvattr, caller_context_t *ct) + int flags, cred_t *cr, boolean_t no_xvattr) { int error = 0; int at_size = 0; vnode_t *use_vp; - xvattr_t tmp_xvattr; - xoptattr_t *xoap = NULL; - uint_t xva_mask; + xvattr_t xvattr; + vattr_t *vap; if (unnamed_vp) { use_vp = unnamed_vp; @@ -354,116 +388,24 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, if ((no_xvattr == B_FALSE) && vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { - /* - * Initialize xvattr, including bzero - */ - xva_init(&tmp_xvattr); - xoap = xva_getxoptattr(&tmp_xvattr); - - ASSERT(xoap); - - /* - * Copy caller-specified classic attributes to tmp_xvattr. - * First save tmp_xvattr's mask (set in xva_init()), which - * contains AT_XVATTR. This is |'d in later if needed. - */ - - xva_mask = tmp_xvattr.xva_vattr.va_mask; - tmp_xvattr.xva_vattr = set_attr->sa_vattr; + smb_vop_setup_xvattr(set_attr, &xvattr); + vap = (vattr_t *)&xvattr; + } else { smb_sa_to_va_mask(set_attr->sa_mask, - &tmp_xvattr.xva_vattr.va_mask); - - /* - * Do not set ctime (only the file system can do it) - */ - - tmp_xvattr.xva_vattr.va_mask &= ~AT_CTIME; - - if (set_attr->sa_mask & SMB_AT_DOSATTR) { - - /* - * "|" in the original xva_mask, which contains - * AT_XVATTR - */ - - tmp_xvattr.xva_vattr.va_mask |= xva_mask; - - XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE); - XVA_SET_REQ(&tmp_xvattr, XAT_SYSTEM); - XVA_SET_REQ(&tmp_xvattr, XAT_READONLY); - XVA_SET_REQ(&tmp_xvattr, XAT_HIDDEN); - - /* - * set_attr->sa_dosattr: If a given bit is not set, - * that indicates that the corresponding field needs - * to be updated with a "0" value. This is done - * implicitly as the xoap->xoa_* fields were bzero'd. - */ - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_ARCHIVE) - xoap->xoa_archive = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_SYSTEM) - xoap->xoa_system = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_READONLY) - xoap->xoa_readonly = 1; - - if (set_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) - xoap->xoa_hidden = 1; - } - - if (set_attr->sa_mask & SMB_AT_CRTIME) { - /* - * "|" in the original xva_mask, which contains - * AT_XVATTR - */ - - tmp_xvattr.xva_vattr.va_mask |= xva_mask; - XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME); - xoap->xoa_createtime = set_attr->sa_crtime; - } - - if ((error = VOP_SETATTR(use_vp, (vattr_t *)&tmp_xvattr, flags, - cr, ct)) != 0) - return (error); - - /* - * If the size of the stream needs to be set, set it on - * the stream file directly. (All other indicated attributes - * are set on the stream's unnamed stream, above.) - */ - - if (at_size) { - /* - * set_attr->sa_vattr.va_size already contains the - * size as set by the caller - * - * Note that vp is used here, and not use_vp. - * Also, only AT_SIZE is needed. - */ + &set_attr->sa_vattr.va_mask); + vap = &set_attr->sa_vattr; + } - set_attr->sa_vattr.va_mask = AT_SIZE; - error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, - cr, ct); - } + if ((error = VOP_SETATTR(use_vp, vap, flags, cr, &smb_ct)) != 0) return (error); - } - /* - * Support for file systems without VFSFT_XVATTR or no_xvattr == B_TRUE - */ - smb_sa_to_va_mask(set_attr->sa_mask, &set_attr->sa_vattr.va_mask); + /* - * set_attr->sa_vattr already contains new values - * as set by the caller + * If the size of the stream needs to be set, set it on + * the stream file directly. (All other indicated attributes + * are set on the stream's unnamed stream, above.) */ - error = VOP_SETATTR(use_vp, &set_attr->sa_vattr, flags, cr, ct); - - if (error != 0) - return (error); - if (at_size) { /* * set_attr->sa_vattr.va_size already contains the @@ -474,8 +416,10 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *set_attr, */ set_attr->sa_vattr.va_mask = AT_SIZE; - error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, ct); + error = VOP_SETATTR(vp, &set_attr->sa_vattr, flags, cr, + &smb_ct); } + return (error); } @@ -531,7 +475,7 @@ smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, cred_t *cr) int smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, - int flags, vnode_t *rootvp, cred_t *cr, caller_context_t *ct) + int flags, vnode_t *rootvp, cred_t *cr) { int error = 0; int option_flags = 0; @@ -578,7 +522,7 @@ smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, pn_alloc(&rpn); error = VOP_LOOKUP(dvp, name, vpp, NULL, option_flags, NULL, cr, - ct, NULL, &rpn); + &smb_ct, NULL, &rpn); if ((error == 0) && od_name) { bzero(od_name, MAXNAMELEN); @@ -594,25 +538,34 @@ smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, char *od_name, int smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, - int flags, cred_t *cr, caller_context_t *ct, vsecattr_t *vsap) + int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; + xvattr_t xvattr; + vattr_t *vap; if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; - smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); + attr->sa_vattr.va_mask = 0; + + if (vfs_has_feature(dvp->v_vfsp, VFSFT_XVATTR)) { + smb_vop_setup_xvattr(attr, &xvattr); + vap = (vattr_t *)&xvattr; + } else { + smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); + vap = &attr->sa_vattr; + } - error = VOP_CREATE(dvp, name, &attr->sa_vattr, EXCL, - attr->sa_vattr.va_mode, vpp, cr, option_flags, ct, vsap); + error = VOP_CREATE(dvp, name, vap, EXCL, attr->sa_vattr.va_mode, + vpp, cr, option_flags, &smb_ct, vsap); return (error); } int -smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -620,7 +573,7 @@ smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, if (flags & SMB_IGNORE_CASE) option_flags = FIGNORECASE; - error = VOP_REMOVE(dvp, name, cr, ct, option_flags); + error = VOP_REMOVE(dvp, name, cr, &smb_ct, option_flags); return (error); } @@ -633,7 +586,7 @@ smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, - char *to_name, int flags, cred_t *cr, caller_context_t *ct) + char *to_name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -643,14 +596,14 @@ smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, option_flags = FIGNORECASE; error = VOP_RENAME(from_dvp, from_name, to_dvp, to_name, cr, - ct, option_flags); + &smb_ct, option_flags); return (error); } int smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, - int flags, cred_t *cr, caller_context_t *ct, vsecattr_t *vsap) + int flags, cred_t *cr, vsecattr_t *vsap) { int error; int option_flags = 0; @@ -662,7 +615,7 @@ smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); - error = VOP_MKDIR(dvp, name, &attr->sa_vattr, vpp, cr, ct, + error = VOP_MKDIR(dvp, name, &attr->sa_vattr, vpp, cr, &smb_ct, option_flags, vsap); return (error); @@ -677,8 +630,7 @@ smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, vnode_t **vpp, */ int -smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr) { int error; int option_flags = 0; @@ -698,16 +650,94 @@ smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, * remove. */ - error = VOP_RMDIR(dvp, name, rootdir, cr, ct, option_flags); + error = VOP_RMDIR(dvp, name, rootdir, cr, &smb_ct, option_flags); return (error); } int -smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct) +smb_vop_commit(vnode_t *vp, cred_t *cr) +{ + return (VOP_FSYNC(vp, 1, cr, &smb_ct)); +} + +void +smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr) { - return (VOP_FSYNC(vp, 1, cr, ct)); + xoptattr_t *xoap = NULL; + uint_t xva_mask; + + /* + * Initialize xvattr, including bzero + */ + xva_init(xvattr); + xoap = xva_getxoptattr(xvattr); + + ASSERT(xoap); + + /* + * Copy caller-specified classic attributes to xvattr. + * First save xvattr's mask (set in xva_init()), which + * contains AT_XVATTR. This is |'d in later if needed. + */ + + xva_mask = xvattr->xva_vattr.va_mask; + xvattr->xva_vattr = smb_attr->sa_vattr; + + smb_sa_to_va_mask(smb_attr->sa_mask, &xvattr->xva_vattr.va_mask); + + /* + * Do not set ctime (only the file system can do it) + */ + + xvattr->xva_vattr.va_mask &= ~AT_CTIME; + + if (smb_attr->sa_mask & SMB_AT_DOSATTR) { + + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + xvattr->xva_vattr.va_mask |= xva_mask; + + XVA_SET_REQ(xvattr, XAT_ARCHIVE); + XVA_SET_REQ(xvattr, XAT_SYSTEM); + XVA_SET_REQ(xvattr, XAT_READONLY); + XVA_SET_REQ(xvattr, XAT_HIDDEN); + + /* + * smb_attr->sa_dosattr: If a given bit is not set, + * that indicates that the corresponding field needs + * to be updated with a "0" value. This is done + * implicitly as the xoap->xoa_* fields were bzero'd. + */ + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_ARCHIVE) + xoap->xoa_archive = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_SYSTEM) + xoap->xoa_system = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_READONLY) + xoap->xoa_readonly = 1; + + if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN) + xoap->xoa_hidden = 1; + } + + if (smb_attr->sa_mask & SMB_AT_CRTIME) { + /* + * "|" in the original xva_mask, which contains + * AT_XVATTR + */ + + xvattr->xva_vattr.va_mask |= xva_mask; + XVA_SET_REQ(xvattr, XAT_CREATETIME); + xoap->xoa_createtime = smb_attr->sa_crtime; + } } + /* * smb_vop_readdir() * @@ -724,8 +754,7 @@ smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct) 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, - caller_context_t *ct) + ino64_t *inop, vnode_t **vpp, char *od_name, int flags, cred_t *cr) { int num_bytes; int error = 0; @@ -737,7 +766,6 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, ASSERT(namelen); ASSERT(inop); ASSERT(cr); - ASSERT(ct); if (dvp->v_type != VDIR) { *namelen = 0; @@ -759,7 +787,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, */ while ((error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep, - &num_bytes, cr, ct, flags)) == 0) { + &num_bytes, cr, flags)) == 0) { if (num_bytes <= 0) break; @@ -767,7 +795,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, name[0] = '\0'; error = smb_vop_readdir_entry(dvp, cookiep, name, namelen, - inop, vpp, od_name, flags, cr, ct, dirbuf, + inop, vpp, od_name, flags, cr, dirbuf, num_bytes); if (error) @@ -815,7 +843,7 @@ smb_vop_readdir(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, static int smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, - cred_t *cr, caller_context_t *ct, int flags) + cred_t *cr, int flags) { int error = 0; int rdirent_flags = 0; @@ -856,7 +884,7 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, auio.uio_fmode = 0; (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); - error = VOP_READDIR(vp, &auio, cr, &sink, ct, rdirent_flags); + error = VOP_READDIR(vp, &auio, cr, &sink, &smb_ct, rdirent_flags); VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); if (error) { @@ -900,7 +928,7 @@ smb_vop_readdir_readpage(vnode_t *vp, void *buf, uint32_t offset, int *count, 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, - caller_context_t *ct, char *dirbuf, int num_bytes) + char *dirbuf, int num_bytes) { uint32_t next_cookie; int ebufsize; @@ -969,7 +997,7 @@ smb_vop_readdir_entry(vnode_t *dvp, uint32_t *cookiep, char *name, int *namelen, */ error = smb_vop_lookup(dvp, edp->ed_name, vpp ? vpp : &vp, - od_name, 0, NULL, cr, ct); + od_name, 0, NULL, cr); if (error) { if (error == ENOENT) { @@ -1080,8 +1108,7 @@ smb_vop_getdents( char *pattern, uint32_t flags, smb_request_t *sr, - cred_t *cr, - caller_context_t *ct) + cred_t *cr) { int error = 0; int maxentries; @@ -1107,13 +1134,13 @@ smb_vop_getdents( num_bytes = SMB_MINLEN_RDDIR_BUF; error = smb_vop_readdir_readpage(dvp, dirbuf, *cookiep, - &num_bytes, cr, ct, flags); + &num_bytes, cr, flags); if (error || (num_bytes <= 0)) break; error = smb_vop_getdents_entries(dir_snode, cookiep, dircountp, - arg, flags, sr, cr, ct, dirbuf, &maxentries, num_bytes, + arg, flags, sr, cr, dirbuf, &maxentries, num_bytes, pattern); if (error) @@ -1158,7 +1185,6 @@ smb_vop_getdents_entries( uint32_t flags, struct smb_request *sr, cred_t *cr, - caller_context_t *ct, char *dirbuf, int *maxentries, int num_bytes, @@ -1219,7 +1245,7 @@ smb_vop_getdents_entries( } error = smb_vop_lookup(dvp, edp->ed_name, &fvp, - NULL, 0, NULL, cr, ct); + NULL, 0, NULL, cr); if (error) { if (error == ENOENT) { @@ -1335,14 +1361,14 @@ smb_vop_getdents_entries( int smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, char *od_name, vnode_t **xattrdirvpp, int flags, vnode_t *rootvp, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { char *solaris_stream_name; char *name; int error; if ((error = smb_vop_lookup_xattrdir(fvp, xattrdirvpp, - LOOKUP_XATTR | CREATE_XATTR_DIR, cr, ct)) != 0) + LOOKUP_XATTR | CREATE_XATTR_DIR, cr)) != 0) return (error); /* @@ -1361,7 +1387,7 @@ smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, name = kmem_zalloc(MAXNAMELEN, KM_SLEEP); if ((error = smb_vop_lookup(*xattrdirvpp, solaris_stream_name, vpp, - name, flags, rootvp, cr, ct)) != 0) { + name, flags, rootvp, cr)) != 0) { VN_RELE(*xattrdirvpp); } else { (void) strlcpy(od_name, &(name[SMB_STREAM_PREFIX_LEN]), @@ -1376,14 +1402,13 @@ smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, vnode_t **vpp, int smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, - vnode_t **vpp, vnode_t **xattrdirvpp, int flags, cred_t *cr, - caller_context_t *ct) + vnode_t **vpp, vnode_t **xattrdirvpp, int flags, cred_t *cr) { char *solaris_stream_name; int error; if ((error = smb_vop_lookup_xattrdir(fvp, xattrdirvpp, - LOOKUP_XATTR | CREATE_XATTR_DIR, cr, ct)) != 0) + LOOKUP_XATTR | CREATE_XATTR_DIR, cr)) != 0) return (error); /* @@ -1395,7 +1420,7 @@ smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, stream_name); if ((error = smb_vop_create(*xattrdirvpp, solaris_stream_name, attr, - vpp, flags, cr, ct, NULL)) != 0) + vpp, flags, cr, NULL)) != 0) VN_RELE(*xattrdirvpp); kmem_free(solaris_stream_name, MAXNAMELEN); @@ -1404,15 +1429,14 @@ smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr, } int -smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr) { char *solaris_stream_name; vnode_t *xattrdirvp; int error; - if ((error = smb_vop_lookup_xattrdir(vp, &xattrdirvp, LOOKUP_XATTR, cr, - ct)) != 0) + if ((error = smb_vop_lookup_xattrdir(vp, &xattrdirvp, LOOKUP_XATTR, cr)) + != 0) return (error); /* @@ -1424,7 +1448,7 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, stream_name); /* XXX might have to use kcred */ - error = smb_vop_remove(xattrdirvp, solaris_stream_name, flags, cr, ct); + error = smb_vop_remove(xattrdirvp, solaris_stream_name, flags, cr); kmem_free(solaris_stream_name, MAXNAMELEN); @@ -1444,7 +1468,7 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr, 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, caller_context_t *ct) + int flags, cred_t *cr) { int nsize = MAXNAMELEN-1; int error = 0; @@ -1454,7 +1478,7 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, vnode_t *vp; if ((error = smb_vop_lookup_xattrdir(fvp, &xattrdirvp, LOOKUP_XATTR, - cr, ct)) != 0) + cr)) != 0) return (error); bzero(stream_info->name, sizeof (stream_info->name)); @@ -1464,7 +1488,7 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, for (;;) { error = smb_vop_readdir(xattrdirvp, cookiep, tmp_name, &nsize, - &ino, &vp, NULL, flags | SMB_STREAM_RDDIR, cr, ct); + &ino, &vp, NULL, flags | SMB_STREAM_RDDIR, cr); if (error || (*cookiep == SMB_EOF)) break; @@ -1504,12 +1528,12 @@ smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, int smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, int flags, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; - error = VOP_LOOKUP(fvp, "", xattrdirvpp, NULL, flags, NULL, cr, ct, - NULL, NULL); + error = VOP_LOOKUP(fvp, "", xattrdirvpp, NULL, flags, NULL, cr, + &smb_ct, NULL, NULL); return (error); } @@ -1560,7 +1584,7 @@ smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr) */ int smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, - cred_t *cr, caller_context_t *ct) + cred_t *cr) { int error; vsecattr_t vsecattr; @@ -1585,7 +1609,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, return (EINVAL); } - if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, ct)) + if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct)) return (error); *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type); @@ -1601,8 +1625,7 @@ smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, * Writes the given ACL in aclp for the specified file. */ int -smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, - caller_context_t *ct) +smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr) { int error; vsecattr_t vsecattr; @@ -1615,7 +1638,7 @@ smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, if (error == 0) { (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); - error = VOP_SETSECATTR(vp, &vsecattr, flags, cr, ct); + error = VOP_SETSECATTR(vp, &vsecattr, flags, cr, &smb_ct); VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); } @@ -1713,3 +1736,93 @@ smb_vop_eaccess(vnode_t *vp, int *mode, int flags, vnode_t *dir_vp, cred_t *cr) } } } + +/* + * smb_vop_shrlock() + * + * See comments for smb_fsop_shrlock() + */ + +int +smb_vop_shrlock(vnode_t *vp, uint32_t uniq_fid, uint32_t desired_access, + uint32_t share_access, cred_t *cr) +{ + struct shrlock shr; + struct shr_locowner shr_own; + short new_access = 0; + short deny = 0; + int flag = 0; + int cmd; + + cmd = (nbl_need_check(vp)) ? F_SHARE_NBMAND : F_SHARE; + + /* + * Check if this is a metadata access + */ + + if ((desired_access & FILE_DATA_ALL) == 0) { + new_access |= F_MDACC; + } else { + if (desired_access & (ACE_READ_DATA | ACE_EXECUTE)) { + new_access |= F_RDACC; + flag |= FREAD; + } + + if (desired_access & (ACE_WRITE_DATA | ACE_APPEND_DATA | + ACE_ADD_FILE)) { + new_access |= F_WRACC; + flag |= FWRITE; + } + + if (SMB_DENY_READ(share_access)) { + deny |= F_RDDNY; + } + + if (SMB_DENY_WRITE(share_access)) { + deny |= F_WRDNY; + } + + if (cmd == F_SHARE_NBMAND) { + if (desired_access & ACE_DELETE) + new_access |= F_RMACC; + + if (SMB_DENY_DELETE(share_access)) { + deny |= F_RMDNY; + } + } + } + + shr.s_access = new_access; + shr.s_deny = deny; + shr.s_sysid = smb_ct.cc_sysid; + shr.s_pid = uniq_fid; + shr.s_own_len = sizeof (shr_own); + shr.s_owner = (caddr_t)&shr_own; + shr_own.sl_id = shr.s_sysid; + shr_own.sl_pid = shr.s_pid; + + return (VOP_SHRLOCK(vp, cmd, &shr, flag, cr, NULL)); +} + +int +smb_vop_unshrlock(vnode_t *vp, uint32_t uniq_fid, cred_t *cr) +{ + struct shrlock shr; + struct shr_locowner shr_own; + + /* + * For s_access and s_deny, we do not need to pass in the original + * values. + */ + + shr.s_access = 0; + shr.s_deny = 0; + shr.s_sysid = smb_ct.cc_sysid; + shr.s_pid = uniq_fid; + shr.s_own_len = sizeof (shr_own); + shr.s_owner = (caddr_t)&shr_own; + shr_own.sl_id = shr.s_sysid; + shr_own.sl_pid = shr.s_pid; + + return (VOP_SHRLOCK(vp, F_UNSHARE, &shr, 0, cr, NULL)); +} diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c index 93b9f6e758..79a0ed82ec 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -78,8 +78,7 @@ smb_com_write(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -104,7 +103,7 @@ smb_com_write(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -151,8 +150,7 @@ smb_com_write_and_close(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -180,13 +178,13 @@ smb_com_write_and_close(struct smb_request *sr) if (rc != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } if ((rc = smb_common_close(sr, last_write)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -219,7 +217,7 @@ smb_com_write_and_unlock(struct smb_request *sr) int rc = 0; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { - smbsr_raise_error(sr, ERRDOS, ERRnoaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); /* NOTREACHED */ } @@ -236,8 +234,7 @@ smb_com_write_and_unlock(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -259,7 +256,7 @@ smb_com_write_and_unlock(struct smb_request *sr) if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } @@ -267,7 +264,8 @@ smb_com_write_and_unlock(struct smb_request *sr) (uint64_t)param->w_count); if (result != NT_STATUS_SUCCESS) { kmem_free(param, sizeof (smb_write_param_t)); - smb_unlock_range_raise_error(sr, result); + smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED, + ERRDOS, ERRnotlocked); /* NOTREACHED */ } @@ -324,15 +322,14 @@ smb_com_write_andx(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } if (SMB_WRMODE_IS_STABLE(param->w_mode) && STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_error(sr, ERRSRV, ERRaccess); + smbsr_error(sr, 0, ERRSRV, ERRaccess); /* NOTREACHED */ } @@ -349,7 +346,7 @@ smb_com_write_andx(struct smb_request *sr) if (param->w_count != 0) { if ((rc = smb_write_common(sr, param)) != 0) { kmem_free(param, sizeof (smb_write_param_t)); - smbsr_raise_errno(sr, rc); + smbsr_errno(sr, rc); /* NOTREACHED */ } } @@ -381,10 +378,9 @@ smb_write_common(struct smb_request *sr, smb_write_param_t *param) if (node->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, node, param->w_offset, - param->w_count, FILE_WRITE_DATA); + param->w_count, B_TRUE); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, rc, ERRSRV, ERRaccess); /* NOTREACHED */ } } @@ -444,35 +440,49 @@ smb_write_truncate(struct smb_request *sr, smb_write_param_t *param) { struct smb_ofile *ofile = sr->fid_ofile; smb_node_t *node = ofile->f_node; + boolean_t append_only = B_FALSE; int rc; if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) return (0); - if (node->attr.sa_vattr.va_type != VDIR) { - rc = smb_lock_range_access(sr, node, param->w_offset, - param->w_count, FILE_WRITE_DATA); + rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, FILE_WRITE_DATA); + if (rc != NT_STATUS_SUCCESS) { + rc = smb_ofile_access(sr->fid_ofile, sr->user_cr, + FILE_APPEND_DATA); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, + ERROR_ACCESS_DENIED); /* NOTREACHED */ + } else { + append_only = B_TRUE; } } - /* - * XXX what if the file has been opened only with - * FILE_APPEND_DATA? - */ - rc = smb_ofile_access(ofile, sr->user_cr, FILE_WRITE_DATA); - if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, NT_STATUS_ACCESS_DENIED, - ERRDOS, ERROR_ACCESS_DENIED); + smb_rwx_xenter(&node->n_lock); + + if (append_only && (param->w_offset < node->n_size)) { + smb_rwx_xexit(&node->n_lock); + smbsr_error(sr, NT_STATUS_ACCESS_DENIED, + ERRDOS, ERRnoaccess); /* NOTREACHED */ } + if (node->attr.sa_vattr.va_type != VDIR) { + rc = smb_lock_range_access(sr, node, param->w_offset, + param->w_count, B_TRUE); + if (rc != NT_STATUS_SUCCESS) { + smb_rwx_xexit(&node->n_lock); + smbsr_error(sr, rc, ERRSRV, ERRaccess); + /* NOTREACHED */ + } + } + node->flags |= NODE_FLAGS_SET_SIZE; node->n_size = param->w_offset; + smb_rwx_xexit(&node->n_lock); + if ((rc = smb_set_file_size(sr)) != 0) return (rc); diff --git a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c index 5d02179cc2..4c7fcb6f81 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write_raw.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write_raw.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -216,6 +216,7 @@ smb_com_write_raw(struct smb_request *sr) unsigned int stability; struct mbuf_chain reply; smb_node_t *fnode; + smb_error_t err; if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { return (SDRC_DROP_VC); @@ -244,8 +245,7 @@ smb_com_write_raw(struct smb_request *sr) sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); if (sr->fid_ofile == NULL) { - smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, - ERRDOS, ERRbadfid); + smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); /* NOTREACHED */ } @@ -260,10 +260,9 @@ smb_com_write_raw(struct smb_request *sr) */ if (fnode->attr.sa_vattr.va_type != VDIR) { rc = smb_lock_range_access(sr, fnode, off, - count, FILE_WRITE_DATA); + count, B_TRUE); if (rc != NT_STATUS_SUCCESS) { - smbsr_raise_cifs_error(sr, rc, - ERRSRV, ERRaccess); + smbsr_error(sr, rc, ERRSRV, ERRaccess); /* NOTREACHED */ } } @@ -440,8 +439,10 @@ notify_write_raw_complete: * If we had an error fill in the appropriate error code */ if (rc != 0) { - (void) smbsr_set_errno(sr, rc); + smbsr_map_errno(rc, &err); + smbsr_set_error(sr, &err); } + /* * Free raw write buffer if present (from smb_transfer_write_raw_data) */ diff --git a/usr/src/uts/common/smbsrv/cifs.h b/usr/src/uts/common/smbsrv/cifs.h index 4533a21bb6..1f657a2d8c 100644 --- a/usr/src/uts/common/smbsrv/cifs.h +++ b/usr/src/uts/common/smbsrv/cifs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -421,6 +421,23 @@ extern "C" { #define SMB_DA_WRITE_THROUGH 0x4000 /* + * Macros used for share reservation rule checking + */ + +#define SMB_DENY_READ(share_access) ((share_access & FILE_SHARE_READ) == 0) + +#define SMB_DENY_WRITE(share_access) ((share_access & FILE_SHARE_WRITE) == 0) + +#define SMB_DENY_DELETE(share_access) ((share_access & FILE_SHARE_DELETE) == 0) + +#define SMB_DENY_RW(share_access) \ + ((share_access & (FILE_SHARE_READ | FILE_SHARE_WRITE)) == 0) + +#define SMB_DENY_ALL(share_access) (share_access == 0) + +#define SMB_DENY_NONE(share_access) (share_access == FILE_SHARE_ALL) + +/* * The SMB open function determines what action should be taken depending * on the existence or lack thereof of files used in the operation. It * has the following mapping: diff --git a/usr/src/uts/common/smbsrv/lmshare.h b/usr/src/uts/common/smbsrv/lmshare.h index db41a5bdee..218bb86df8 100644 --- a/usr/src/uts/common/smbsrv/lmshare.h +++ b/usr/src/uts/common/smbsrv/lmshare.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -163,7 +163,6 @@ extern DWORD lmshrd_iterate(uint64_t iterator, lmshare_info_t *si); extern DWORD lmshrd_list(int offset, lmshare_list_t *list); extern DWORD lmshrd_list_transient(int offset, lmshare_list_t *list); extern DWORD lmshrd_num_transient(void); -extern int lmshrd_dump_hash(char *logfname); #endif extern int lmshrd_num_shares(void); extern DWORD lmshrd_delete(char *share_name); diff --git a/usr/src/uts/common/smbsrv/lmshare_door.h b/usr/src/uts/common/smbsrv/lmshare_door.h index c1c6f2ba0c..4e4413bc9a 100644 --- a/usr/src/uts/common/smbsrv/lmshare_door.h +++ b/usr/src/uts/common/smbsrv/lmshare_door.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,9 +70,9 @@ extern "C" { #define SMB_GET_KCONFIG 17 -void smb_load_kconfig(smb_kmod_cfg_t *cfg); -void smb_dr_get_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); -void smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); +void smb_load_kconfig(smb_kmod_cfg_t *); +void smb_dr_get_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); +void smb_dr_put_kconfig(smb_dr_ctx_t *, smb_kmod_cfg_t *); /* * Door server status @@ -97,17 +97,16 @@ void smb_dr_put_kconfig(smb_dr_ctx_t *ctx, smb_kmod_cfg_t *cfg); * }; */ -void smb_dr_get_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si); -void smb_dr_put_lmshare(smb_dr_ctx_t *ctx, lmshare_info_t *si); - -uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *ctx); -void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *ctx, - uint64_t lmshr_iter); -void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *ctx); -void smb_dr_get_lmshr_list(smb_dr_ctx_t *ctx, - lmshare_list_t *shrlist); -void smb_dr_put_lmshr_list(smb_dr_ctx_t *ctx, - lmshare_list_t *shrlist); +void smb_dr_get_lmshare(smb_dr_ctx_t *, lmshare_info_t *); +void smb_dr_put_lmshare(smb_dr_ctx_t *, lmshare_info_t *); + +uint64_t smb_dr_get_lmshr_iterator(smb_dr_ctx_t *); +void smb_dr_put_lmshr_iterator(smb_dr_ctx_t *, uint64_t); +void smb_dr_free_lmshr_iterator(smb_dr_ctx_t *); +void smb_dr_get_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); +void smb_dr_put_lmshr_list(smb_dr_ctx_t *, lmshare_list_t *); + +void lmshrd_door_close(void); #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/lsalib.h b/usr/src/uts/common/smbsrv/lsalib.h index ae4076bf10..535fc9d62b 100644 --- a/usr/src/uts/common/smbsrv/lsalib.h +++ b/usr/src/uts/common/smbsrv/lsalib.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,31 +50,8 @@ extern "C" { /* * lsalib.c */ -int lsa_lookup_builtin_name(char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_local_sam(char *domain, - char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_local(char *name, - smb_userinfo_t *user_info); - -int lsa_lookup_name(char *server, - char *domain, - char *account_name, - smb_userinfo_t *user_info); - -DWORD lsa_lookup_name2(char *server, - char *domain, - char *account_name, - smb_userinfo_t *user_info); - -int lsa_lookup_sid(nt_sid_t *sid, - smb_userinfo_t *user_info); - -DWORD lsa_lookup_sid2(nt_sid_t *sid, - smb_userinfo_t *user_info); +uint32_t lsa_lookup_name(char *, char *, uint16_t, smb_userinfo_t *); +uint32_t lsa_lookup_sid(nt_sid_t *, smb_userinfo_t *); int lsa_lookup_privs(char *server, char *account_name, @@ -111,11 +88,11 @@ int lsar_query_security_desc(mlsvc_handle_t *lsa_handle); DWORD lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass); -int lsar_lookup_names(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info); -int lsar_lookup_sids(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_sids(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info); @@ -145,11 +122,11 @@ DWORD lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *display_name, int display_len); -DWORD lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, smb_userinfo_t *user_info); -DWORD lsar_lookup_names2(mlsvc_handle_t *lsa_handle, +uint32_t lsar_lookup_names2(mlsvc_handle_t *lsa_handle, char *name, smb_userinfo_t *user_info); diff --git a/usr/src/uts/common/smbsrv/mlrpc.h b/usr/src/uts/common/smbsrv/mlrpc.h index 59ea5536fd..ff4d52254c 100644 --- a/usr/src/uts/common/smbsrv/mlrpc.h +++ b/usr/src/uts/common/smbsrv/mlrpc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -213,6 +213,21 @@ typedef struct mlrpc_service { } mlrpc_service_t; /* + * 20-byte opaque id used by various RPC services. + */ +typedef struct ndr_hdid { + uint32_t data[5]; +} ndr_hdid_t; + +typedef struct ndr_handle { + struct ndr_handle *nh_next; + ndr_hdid_t nh_id; + int nh_fid; + const mlrpc_service_t *nh_svc; + void *nh_data; +} ndr_handle_t; + +/* * The list of bindings is anchored at a connection. Nothing in the * RPC mechanism allocates them. Binding elements which have service==0 * indicate free elements. When a connection is instantiated, at least @@ -342,7 +357,8 @@ int mlrpc_heap_avail(mlrpc_heap_t *); #define MLRPC_HEAP_STRSAVE(MXA, STR) \ mlrpc_heap_strsave((MXA)->heap, (STR)) -struct mlrpc_xaction { +typedef struct mlrpc_xaction { + int fid; unsigned short ptype; /* just handy, hi bits spcl */ unsigned short opnum; /* for requests */ struct mlndr_stream recv_mlnds; @@ -353,7 +369,7 @@ struct mlrpc_xaction { struct mlrpc_binding *binding_list; /* from connection */ mlrpc_heap_t *heap; struct mlsvc_rpc_context *context; -}; +} ndr_xa_t; struct mlrpc_client { int (*xa_init)(struct mlrpc_client *, struct mlrpc_xaction *, @@ -371,16 +387,16 @@ struct mlrpc_client { unsigned next_p_cont_id; }; -/* mlndo.c */ +/* ndr_ops.c */ int mlnds_initialize(struct mlndr_stream *, unsigned, int, mlrpc_heap_t *); void mlnds_destruct(struct mlndr_stream *); -/* mlrpc_client.c */ +/* ndr_client.c */ int mlrpc_c_bind(struct mlrpc_client *, char *, struct mlrpc_binding **); int mlrpc_c_call(struct mlrpc_binding *, int, void *, mlrpc_heapref_t *); void mlrpc_c_free_heap(struct mlrpc_binding *, mlrpc_heapref_t *); -/* mlrpc_encdec.c */ +/* ndr_marshal.c */ int mlrpc_encode_decode_common(struct mlrpc_xaction *, int, unsigned, struct ndr_typeinfo *, void *); int mlrpc_decode_call(struct mlrpc_xaction *, void *); @@ -392,24 +408,30 @@ int mlrpc_encode_pdu_hdr(struct mlrpc_xaction *); void mlrpc_decode_frag_hdr(struct mlndr_stream *, mlrpcconn_common_header_t *); unsigned mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *); -/* mlrpc_server.c */ +/* ndr_server.c */ int mlrpc_generic_call_stub(struct mlrpc_xaction *); -/* mlrpc_svc.c */ -struct mlrpc_stub_table *mlrpc_find_stub_in_svc(struct mlrpc_service *, int); -struct mlrpc_service *mlrpc_find_service_by_name(const char *); -struct mlrpc_service *mlrpc_find_service_by_uuids(mlrpc_uuid_t *, int, - mlrpc_uuid_t *, int); -int mlrpc_register_service(struct mlrpc_service *); -void mlrpc_unregister_service(struct mlrpc_service *); -void mlrpc_uuid_to_str(mlrpc_uuid_t *, char *); -int mlrpc_str_to_uuid(char *, mlrpc_uuid_t *); +/* ndr_svc.c */ +struct mlrpc_stub_table *mlrpc_find_stub_in_svc(mlrpc_service_t *, int); +mlrpc_service_t *mlrpc_find_service_by_name(const char *); +mlrpc_service_t *mlrpc_find_service_by_uuids(ndr_uuid_t *, int, + ndr_uuid_t *, int); +int mlrpc_register_service(mlrpc_service_t *); +void mlrpc_unregister_service(mlrpc_service_t *); +void mlrpc_uuid_to_str(ndr_uuid_t *, char *); +int mlrpc_str_to_uuid(char *, ndr_uuid_t *); void mlrpc_binding_pool_initialize(struct mlrpc_binding **, struct mlrpc_binding pool[], unsigned); struct mlrpc_binding *mlrpc_find_binding(struct mlrpc_xaction *, mlrpc_p_context_id_t); struct mlrpc_binding *mlrpc_new_binding(struct mlrpc_xaction *); +ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *); +void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *); +ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *); +void ndr_hdclose(int fid); + + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/smbsrv/mlsvc.h b/usr/src/uts/common/smbsrv/mlsvc.h index 6177d9fbaf..a85066fc9f 100644 --- a/usr/src/uts/common/smbsrv/mlsvc.h +++ b/usr/src/uts/common/smbsrv/mlsvc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,17 +152,10 @@ char *mlsvc_ipc_name(int ipc_type, char *username); * the encrypted passwords. */ -int mlsvc_logon(char *domain_controller, char *domain_name, - char *username); -int mlsvc_echo(char *server); -int mlsvc_open_pipe(char *hostname, char *domain, char *username, - char *pipename); -int mlsvc_close_pipe(int fid); void mlsvc_nt_password_hash(char *result, char *password); int mlsvc_encrypt_nt_password(char *password, char *key, int keylen, char *out, int outmax); DWORD mlsvc_join(char *server, char *domain, char *username, char *password); -int mlsvc_locate_domain_controller(char *domain); /* * RPC request processing interface (mlsvc_server.c). @@ -198,16 +191,8 @@ typedef struct mlsvc_pipe { struct mlsvc_rpc_context *mlrpc_process(int, smb_dr_user_ctx_t *); struct mlsvc_rpc_context *mlrpc_lookup(int fid); void mlrpc_release(int); -int mlsvc_session_native_values(int fid, int *remote_os, int *remote_lm, - int *pdc_type); void mlsvc_rpc_report_status(int opnum, DWORD status); -/* - * This is a temporary location for this NETLOGON stuff. - */ -typedef int (*mlsvc_locate_pdc_t)(char *domain); -void mlsvc_install_pdc_cb(mlsvc_locate_pdc_t locate_pdc_cb); - #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/smbsrv/mlsvc_util.h b/usr/src/uts/common/smbsrv/mlsvc_util.h index e9ababec15..24e6bdd1a9 100644 --- a/usr/src/uts/common/smbsrv/mlsvc_util.h +++ b/usr/src/uts/common/smbsrv/mlsvc_util.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,72 +48,12 @@ extern "C" { #endif -/* - * Predefined global RIDs. - */ -#define MLSVC_DOMAIN_GROUP_RID_ADMINS 0x00000200L -#define MLSVC_DOMAIN_GROUP_RID_USERS 0x00000201L -#define MLSVC_DOMAIN_GROUP_RID_GUESTS 0x00000202L -#define MLSVC_DOMAIN_GROUP_RID_COMPUTERS 0x00000203L -#define MLSVC_DOMAIN_GROUP_RID_CONTROLLERS 0x00000204L -#define MLSVC_DOMAIN_GROUP_RID_CERT_ADMINS 0x00000205L -#define MLSVC_DOMAIN_GROUP_RID_SCHEMA_ADMINS 0x00000206L - -/* - * Predefined local alias RIDs. - */ -#define MLSVC_LOCAL_GROUP_RID_ADMINS 0x00000220L -#define MLSVC_LOCAL_GROUP_RID_USERS 0x00000221L -#define MLSVC_LOCAL_GROUP_RID_GUESTS 0x00000222L -#define MLSVC_LOCAL_GROUP_RID_POWER_USERS 0x00000223L -#define MLSVC_LOCAL_GROUP_RID_ACCOUNT_OPS 0x00000224L -#define MLSVC_LOCAL_GROUP_RID_SERVER_OPS 0x00000225L -#define MLSVC_LOCAL_GROUP_RID_PRINT_OPS 0x00000226L -#define MLSVC_LOCAL_GROUP_RID_BACKUP_OPS 0x00000227L -#define MLSVC_LOCAL_GROUP_RID_REPLICATOR 0x00000228L - -/* - * All predefined local group RIDs belong - * to a special domain called BUILTIN. - */ -#define MLSVC_BUILTIN_DOMAIN_NAME "BUILTIN" -#define MLSVC_BUILTIN_DOMAIN_SIDSTRLEN 8 - -/* - * Universal and NT well-known SIDs - */ -#define MLSVC_NULL_SIDSTR "S-1-0-0" -#define MSLVC_WORLD_SIDSTR "S-1-1-0" -#define MSLVC_LOCAL_SIDSTR "S-1-2-0" -#define MSLVC_CREATOR_OWNER_ID_SIDSTR "S-1-3-0" -#define MSLVC_CREATOR_GROUP_ID_SIDSTR "S-1-3-1" -#define MSLVC_CREATOR_OWNER_SERVER_ID_SIDSTR "S-1-3-2" -#define MSLVC_CREATOR_GROUP_SERVER_ID_SIDSTR "S-1-3-3" -#define MSLVC_NON_UNIQUE_IDS_SIDSTR "S-1-4" -#define MLSVC_NT_AUTHORITY_SIDSTR "S-1-5" -#define MLSVC_DIALUP_SIDSTR "S-1-5-1" -#define MLSVC_NETWORK_SIDSTR "S-1-5-2" -#define MLSVC_BATCH_SIDSTR "S-1-5-3" -#define MLSVC_INTERACTIVE_SIDSTR "S-1-5-4" -#define MLSVC_SERVICE_SIDSTR "S-1-5-6" -#define MLSVC_ANONYMOUS_LOGON_SIDSTR "S-1-5-7" -#define MLSVC_PROXY_SIDSTR "S-1-5-8" -#define MLSVC_SERVER_LOGON_SIDSTR "S-1-5-9" -#define MLSVC_SELF_SIDSTR "S-1-5-10" -#define MLSVC_AUTHENTICATED_USER_SIDSTR "S-1-5-11" -#define MLSVC_RESTRICTED_CODE_SIDSTR "S-1-5-12" -#define MLSVC_NT_LOCAL_SYSTEM_SIDSTR "S-1-5-18" -#define MLSVC_NT_NON_UNIQUE_SIDSTR "S-1-5-21" -#define MLSVC_BUILTIN_DOMAIN_SIDSTR "S-1-5-32" - -int mlsvc_lookup_name(char *domain, char *name, nt_sid_t **sid); -int mlsvc_lookup_sid(nt_sid_t *sid, char *buf, int bufsize); - 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); +extern int mlsvc_is_local_domain(const char *); /* * The definition of a local unique id (LUID). This is an opaque id @@ -148,38 +88,6 @@ typedef struct ms_handle { } ms_handle_t; /* - * List of interface specifications: can be used to identify the - * sub-system to which a handle is assigned. The handle management - * library doesn't check or care about the ifspec value. - */ -typedef enum ms_ifspec { - MLSVC_IFSPEC_NULL, - MLSVC_IFSPEC_LSAR, - MLSVC_IFSPEC_SAMR, - MLSVC_IFSPEC_WINREG, - MLSVC_IFSPEC_SVCCTL, - MLSVC_IFSPEC_SPOOLSS, - MLSVC_IFSPEC_LOGR, - MLSVC_IFSPEC_LLSR, - MLSVC_NUM_IFSPECS -} ms_ifspec_t; - -#define MLSVC_HANDLE_KEY_MAX 32 - -typedef struct ms_handle_desc { - struct ms_handle_desc *next; - ms_handle_t handle; - ms_ifspec_t ifspec; - char key[MLSVC_HANDLE_KEY_MAX]; - DWORD discrim; -} ms_handle_desc_t; - -ms_handle_t *mlsvc_get_handle(ms_ifspec_t ifspec, char *key, DWORD discrim); -int mlsvc_put_handle(ms_handle_t *handle); -int mlsvc_validate_handle(ms_handle_t *handle, char *key); -ms_handle_desc_t *mlsvc_lookup_handle(ms_handle_t *handle); - -/* * The mlsvc_rpc_context structure provides the connection binding context * for client RPC calls. This space must be provided by the client library * for use by the underlying RPC library. Note that we need two binding @@ -217,11 +125,6 @@ struct mlsvc_rpc_context { * The context contains a pointer to the top level handle for the * interface, which is assigned during the bind. It's used when closing * to detect when to free the context. - * - * I know this is really tacky but the elements in the descriptor are - * arranged so that a handle can be overlaid directly onto a descriptor. - * I probably won't do this but now you know - just in case you see it - * in the code. */ typedef struct mlsvc_rpc_desc { ms_handle_t handle; diff --git a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl index fd42fcac1c..596329a521 100644 --- a/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl +++ b/usr/src/uts/common/smbsrv/ndl/rpcpdu.ndl @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,7 +46,7 @@ * UUID (Universal Unique IDentifier) */ /* (X/Open CAE Spec Appendix A) */ -struct mlrpc_uuid_dce { +struct ndr_dce_uuid { DWORD time_low; WORD time_mid; WORD time_hi_and_version; @@ -55,13 +55,13 @@ struct mlrpc_uuid_dce { BYTE node[6]; }; -struct mlrpc_uuid { +struct ndr_uuid { DWORD data1; WORD data2; WORD data3; BYTE data4[8]; }; -typedef struct mlrpc_uuid mlrpc_uuid_t; +typedef struct ndr_uuid ndr_uuid_t; /* * Representation label -- needed for RPC header @@ -171,7 +171,7 @@ typedef WORD mlrpc_p_context_id_t; _NO_REORDER_ struct mlrpc_p_syntax_id { - mlrpc_uuid_t if_uuid; + ndr_uuid_t if_uuid; DWORD if_version; }; typedef struct mlrpc_p_syntax_id mlrpc_p_syntax_id_t; @@ -182,7 +182,7 @@ struct mlrpc_p_cont_elem { BYTE n_transfer_syn; BYTE _reserved; mlrpc_p_syntax_id_t abstract_syntax; - /*SIZE_IS(n_transfer_syn)*/ + /*SIZE_IS(n_transfer_syn)*/ mlrpc_p_syntax_id_t transfer_syntaxes[1]; }; typedef struct mlrpc_p_cont_elem mlrpc_p_cont_elem_t; @@ -193,7 +193,7 @@ struct mlrpc_p_cont_list { BYTE n_context_elem; BYTE _reserved; WORD _reserved2; - /*SIZE_IS(n_context_elem)*/ + /*SIZE_IS(n_context_elem)*/ mlrpc_p_cont_elem_t p_cont_elem[1]; }; typedef struct mlrpc_p_cont_list mlrpc_p_cont_list_t; @@ -226,7 +226,7 @@ struct mlrpc_p_result_list { BYTE n_results; BYTE reserved; WORD reserved2; - /*SIZE_IS(n_results)*/ + /*SIZE_IS(n_results)*/ mlrpc_p_result_t p_results[1]; }; typedef struct mlrpc_p_result_list mlrpc_p_result_list_t; @@ -236,10 +236,10 @@ EXTERNTYPEINFO(mlrpc_p_result_list) _NO_REORDER_ struct mlrpc_port_any { WORD length; /* always 18 */ - /*SIZE_IS(length)*/ + /*SIZE_IS(length)*/ BYTE port_spec[MLRPC_PORT_ANY_MAX_PORT_SPEC]; - /* \PIPE\ntsvcs */ - /* We cheat by using 18, and pad on the right with zeroes */ + /* \PIPE\ntsvcs */ + /* We cheat by using 18, and pad on the right with zeroes */ }; typedef struct mlrpc_port_any mlrpc_port_any_t; EXTERNTYPEINFO(mlrpc_port_any) @@ -377,15 +377,15 @@ _NO_REORDER_ struct mlrpcconn_request_hdr { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ WORD opnum; /* 22:02 op number w/i interface */ - /* optional field if PFC_OBJECT_UUID, not present */ - /* mlrpc_uuid_t object; */ + /* optional field if PFC_OBJECT_UUID, not present */ + /* ndr_uuid_t object; */ /* stub-data, 8-octet aligned */ /* 24:nn */ /* nn = frag_len - sizeof(common_header) - auth_len */ @@ -399,19 +399,19 @@ _NO_REORDER_ struct mlrpcconn_request_hdr_with_object { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ WORD opnum; /* 22:02 op number w/i interface */ - /* optional field if PFC_OBJECT_UUID, is present */ - mlrpc_uuid_t object; /* 24:16 object UUID, unknown purpose*/ + /* optional field if PFC_OBJECT_UUID, is present */ + ndr_uuid_t object; /* 24:16 object UUID, unknown purpose*/ /* stub-data, 8-octet aligned */ /* 28:nn */ /* nn = frag_len - sizeof(common_header) - auth_len */ - /* nn -= sizeof(mlrpc_uuid_t); */ + /* nn -= sizeof(ndr_uuid_t); */ /* optional authentication verifier iff auth_length != 0 */ /* auth_verifier_co_t auth_verifier; */ @@ -435,12 +435,12 @@ _NO_REORDER_ struct mlrpcconn_response_hdr { mlrpcconn_common_header_t common_hdr; /* 00:16 (see above) */ - /* needed for request, response, or fault */ + /* needed for request, response, or fault */ DWORD alloc_hint; /* 16:04 allocation hint */ mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ - /* needed for response or fault */ + /* needed for response or fault */ BYTE cancel_count; /* 22:01 cancel count */ BYTE reserved; /* 23:01 mbz */ @@ -467,17 +467,17 @@ struct mlrpcconn_fault_hdr { mlrpc_p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ - /* needed for response or fault */ + /* needed for response or fault */ BYTE cancel_count; /* 22:01 cancel count */ BYTE reserved; /* 23:01 mbz */ - /* fault code */ + /* fault code */ DWORD status; /* 24:04 run-time fault code or 0 */ - /* pad to 8-byte alignment */ + /* pad to 8-byte alignment */ BYTE reserved2[4]; /* 28:04 must-be-zero */ - /* stub-data here if status==0. We do not use this mode. */ + /* stub-data here if status==0. We do not use this mode. */ /* optional authentication verifier iff auth_length != 0 */ /* auth_verifier_co_t auth_verifier; */ diff --git a/usr/src/uts/common/smbsrv/ndl/winreg.ndl b/usr/src/uts/common/smbsrv/ndl/winreg.ndl index 2d3d1de28d..b1a02a858b 100644 --- a/usr/src/uts/common/smbsrv/ndl/winreg.ndl +++ b/usr/src/uts/common/smbsrv/ndl/winreg.ndl @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,7 +34,10 @@ #include "ndrtypes.ndl" +#define WINREG_OPNUM_OpenHKCR 0x00 +#define WINREG_OPNUM_OpenHKCU 0x01 #define WINREG_OPNUM_OpenHKLM 0x02 +#define WINREG_OPNUM_OpenHKPD 0x03 #define WINREG_OPNUM_OpenHKUsers 0x04 #define WINREG_OPNUM_Close 0x05 #define WINREG_OPNUM_CreateKey 0x06 @@ -44,34 +47,40 @@ #define WINREG_OPNUM_EnumValue 0x0a #define WINREG_OPNUM_FlushKey 0x0b #define WINREG_OPNUM_GetKeySec 0x0c +#define WINREG_OPNUM_LoadKey 0x0d +#define WINREG_OPNUM_NotifyChange 0x0e #define WINREG_OPNUM_OpenKey 0x0f #define WINREG_OPNUM_QueryKey 0x10 #define WINREG_OPNUM_QueryValue 0x11 +#define WINREG_OPNUM_ReplaceKey 0x12 +#define WINREG_OPNUM_RestoreKey 0x13 +#define WINREG_OPNUM_SaveKey 0x14 #define WINREG_OPNUM_SetKeySec 0x15 #define WINREG_OPNUM_CreateValue 0x16 +#define WINREG_OPNUM_UnloadKey 0x17 #define WINREG_OPNUM_Shutdown 0x18 +#define WINREG_OPNUM_AbortShutdown 0x19 #define WINREG_OPNUM_GetVersion 0x1a - -struct msreg_handle { +struct winreg_handle { DWORD hand1; DWORD hand2; WORD hand3[2]; BYTE hand4[8]; }; -typedef struct msreg_handle msreg_handle_t; +typedef struct winreg_handle winreg_handle_t; -struct msreg_string_desc { +struct winreg_string_desc { WORD length; WORD allosize; LPTSTR str; }; -typedef struct msreg_string_desc msreg_string_t; +typedef struct winreg_string_desc winreg_string_t; /* * Fake Varying/Conformant with a funny conformant. */ -struct msreg_value { +struct winreg_value { DWORD vc_first_is; /* 0 */ DWORD vc_length_is; SIZE_IS(vc_length_is) @@ -84,37 +93,59 @@ struct file_time { }; typedef struct file_time file_time_t; +OPERATION(WINREG_OPNUM_OpenHKCR) +struct winreg_OpenHKCR { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_OpenHKCU) +struct winreg_OpenHKCU { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenHKLM) -struct msreg_OpenHKLM { - IN BYTE whatever[8]; +struct winreg_OpenHKLM { + IN DWORD *server; IN DWORD access_mask; - OUT msreg_handle_t handle; + OUT winreg_handle_t handle; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_OpenHKPD) +struct winreg_OpenHKPD { + IN DWORD *server; + IN DWORD access_mask; + OUT winreg_handle_t handle; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenHKUsers) -struct msreg_OpenHKUsers { - IN BYTE whatever[8]; +struct winreg_OpenHKUsers { + IN DWORD *server; IN DWORD access_mask; - OUT msreg_handle_t handle; + OUT winreg_handle_t handle; OUT DWORD status; }; OPERATION(WINREG_OPNUM_Close) -struct msreg_Close { - IN msreg_handle_t handle; - OUT msreg_handle_t result_handle; +struct winreg_Close { + IN winreg_handle_t handle; + OUT winreg_handle_t result_handle; OUT DWORD status; }; OPERATION(WINREG_OPNUM_CreateKey) -struct msreg_CreateKey { - IN msreg_handle_t handle; - IN msreg_string_t subkey; +struct winreg_CreateKey { + IN winreg_handle_t handle; + IN winreg_string_t subkey; /* IN ignore the remaining input data */ OUT DWORD status; @@ -122,9 +153,9 @@ struct msreg_CreateKey { OPERATION(WINREG_OPNUM_DeleteKey) -struct msreg_DeleteKey { - IN msreg_handle_t handle; - IN msreg_string_t subkey; +struct winreg_DeleteKey { + IN winreg_handle_t handle; + IN winreg_string_t subkey; /* IN ignore the remaining input data */ OUT DWORD status; @@ -132,9 +163,9 @@ struct msreg_DeleteKey { OPERATION(WINREG_OPNUM_DeleteValue) -struct msreg_DeleteValue { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_DeleteValue { + IN winreg_handle_t handle; + IN winreg_string_t name; /* IN ignore the remaining input data */ OUT DWORD status; @@ -146,27 +177,48 @@ struct msreg_DeleteValue { * as IN parameters but we can ignore them. */ OPERATION(WINREG_OPNUM_EnumValue) -struct msreg_EnumValue { - IN msreg_handle_t handle; - IN DWORD index; +struct winreg_EnumValue { + IN winreg_handle_t handle; + IN DWORD index; /* IN ignore the remaining input data */ - OUT msreg_string_t name; + OUT winreg_string_t name; OUT DWORD *type; - OUT struct msreg_value *value; + OUT struct winreg_value *value; OUT DWORD *value_size; OUT DWORD *value_size_total; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_FlushKey) +struct winreg_FlushKey { + IN winreg_handle_t handle; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_GetKeySec) +struct winreg_GetKeySec { + IN winreg_handle_t handle; + IN DWORD sec_info; + OUT DWORD *sd; + OUT DWORD status; +}; + +OPERATION(WINREG_OPNUM_NotifyChange) +struct winreg_NotifyChange { + IN winreg_handle_t handle; + IN DWORD watch_subtree; + IN DWORD notify_filter; + OUT DWORD status; +}; OPERATION(WINREG_OPNUM_OpenKey) -struct msreg_OpenKey { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_OpenKey { + IN winreg_handle_t handle; + IN winreg_string_t name; IN DWORD unknown; IN DWORD access_mask; - OUT msreg_handle_t result_handle; + OUT winreg_handle_t result_handle; OUT DWORD status; }; @@ -183,14 +235,14 @@ struct msreg_OpenKey { */ OPERATION(WINREG_OPNUM_QueryKey) -struct msreg_QueryKey { - IN msreg_handle_t handle; +struct winreg_QueryKey { + IN winreg_handle_t handle; /* * Ignore the remaining input data - * (2 * DWORD, possibly msreg_string_t). + * (2 * DWORD, possibly winreg_string_t). */ - OUT msreg_string_t name; + OUT winreg_string_t name; OUT DWORD unknown; OUT DWORD sub_keys; OUT DWORD max_subkey_len; @@ -209,23 +261,31 @@ struct msreg_QueryKey { * as IN parameters but we can ignore them. */ OPERATION(WINREG_OPNUM_QueryValue) -struct msreg_QueryValue { - IN msreg_handle_t handle; - IN msreg_string_t value_name; +struct winreg_QueryValue { + IN winreg_handle_t handle; + IN winreg_string_t value_name; /* IN ignore the remaining input data */ OUT DWORD *type; - OUT struct msreg_value *value; + OUT struct winreg_value *value; OUT DWORD *value_size; OUT DWORD *value_size_total; OUT DWORD status; }; +OPERATION(WINREG_OPNUM_SetKeySec) +struct winreg_SetKeySec { + IN winreg_handle_t handle; + IN DWORD access_mask; + IN DWORD sd; + OUT DWORD status; +}; + OPERATION(WINREG_OPNUM_CreateValue) -struct msreg_CreateValue { - IN msreg_handle_t handle; - IN msreg_string_t name; +struct winreg_CreateValue { + IN winreg_handle_t handle; + IN winreg_string_t name; /* IN ignore the remaining input data */ OUT DWORD status; @@ -238,17 +298,17 @@ struct msreg_CreateValue { * without anything appearing in the log, and return access denied. */ OPERATION(WINREG_OPNUM_Shutdown) -struct msreg_Shutdown { - IN DWORD ignored; - OUT DWORD status; +struct winreg_Shutdown { + IN DWORD ignored; + OUT DWORD status; }; OPERATION(WINREG_OPNUM_GetVersion) -struct msreg_GetVersion { - IN msreg_handle_t handle; - OUT DWORD version; - OUT DWORD status; +struct winreg_GetVersion { + IN winreg_handle_t handle; + OUT DWORD version; + OUT DWORD status; }; @@ -257,30 +317,44 @@ struct msreg_GetVersion { */ INTERFACE(0) union winreg_interface { + CASE(WINREG_OPNUM_OpenHKCR) + struct winreg_OpenHKCR OpenHKCR; + CASE(WINREG_OPNUM_OpenHKCU) + struct winreg_OpenHKCU OpenHKCU; CASE(WINREG_OPNUM_OpenHKLM) - struct msreg_OpenHKLM OpenHKLM; + struct winreg_OpenHKLM OpenHKLM; + CASE(WINREG_OPNUM_OpenHKPD) + struct winreg_OpenHKPD OpenHKPD; CASE(WINREG_OPNUM_OpenHKUsers) - struct msreg_OpenHKUsers OpenHKUsers; + struct winreg_OpenHKUsers OpenHKUsers; CASE(WINREG_OPNUM_Close) - struct msreg_Close Close; + struct winreg_Close Close; CASE(WINREG_OPNUM_CreateKey) - struct msreg_CreateKey CreateKey; + struct winreg_CreateKey CreateKey; CASE(WINREG_OPNUM_DeleteKey) - struct msreg_DeleteKey DeleteKey; + struct winreg_DeleteKey DeleteKey; CASE(WINREG_OPNUM_DeleteValue) - struct msreg_DeleteValue DeleteValue; + struct winreg_DeleteValue DeleteValue; + CASE(WINREG_OPNUM_FlushKey) + struct winreg_FlushKey FlushKey; + CASE(WINREG_OPNUM_GetKeySec) + struct winreg_GetKeySec GetKeySec; + CASE(WINREG_OPNUM_NotifyChange) + struct winreg_NotifyChange NotifyChange; CASE(WINREG_OPNUM_OpenKey) - struct msreg_OpenKey OpenKey; + struct winreg_OpenKey OpenKey; CASE(WINREG_OPNUM_QueryKey) - struct msreg_QueryKey QueryKey; + struct winreg_QueryKey QueryKey; CASE(WINREG_OPNUM_QueryValue) - struct msreg_QueryValue QueryValue; + struct winreg_QueryValue QueryValue; + CASE(WINREG_OPNUM_SetKeySec) + struct winreg_SetKeySec SetKeySec; CASE(WINREG_OPNUM_CreateValue) - struct msreg_CreateValue CreateValue; + struct winreg_CreateValue CreateValue; CASE(WINREG_OPNUM_Shutdown) - struct msreg_Shutdown Shutdown; + struct winreg_Shutdown Shutdown; CASE(WINREG_OPNUM_GetVersion) - struct msreg_GetVersion GetVersion; + struct winreg_GetVersion GetVersion; }; typedef union winreg_interface winreg_interface_t; EXTERNTYPEINFO(winreg_interface) diff --git a/usr/src/uts/common/smbsrv/samlib.h b/usr/src/uts/common/smbsrv/samlib.h index efec26a922..c38986d1d5 100644 --- a/usr/src/uts/common/smbsrv/samlib.h +++ b/usr/src/uts/common/smbsrv/samlib.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -55,7 +55,7 @@ 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, smb_userinfo_t *user_info); + smb_auth_info_t *auth, DWORD account_flags); DWORD sam_remove_trust_account(char *server, char *domain); diff --git a/usr/src/uts/common/smbsrv/smb_door_svc.h b/usr/src/uts/common/smbsrv/smb_door_svc.h index be8898f42a..6b9b943a6a 100644 --- a/usr/src/uts/common/smbsrv/smb_door_svc.h +++ b/usr/src/uts/common/smbsrv/smb_door_svc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -82,20 +82,8 @@ enum smb_dr_opcode_t { SMB_DR_USER_NONAUTH_LOGON, SMB_DR_USER_AUTH_LOGOFF, SMB_DR_USER_LIST, - SMB_DR_GROUP_ADD, - SMB_DR_GROUP_DELETE, - SMB_DR_GROUP_MEMBER_ADD, - SMB_DR_GROUP_MEMBER_REMOVE, - SMB_DR_GROUP_COUNT, - SMB_DR_GROUP_CACHE_SIZE, - SMB_DR_GROUP_MODIFY, - SMB_DR_GROUP_PRIV_NUM, - SMB_DR_GROUP_PRIV_LIST, - SMB_DR_GROUP_PRIV_GET, - SMB_DR_GROUP_PRIV_SET, - SMB_DR_GROUP_LIST, - SMB_DR_GROUP_MEMBER_LIST, - SMB_DR_GROUP_MEMBER_COUNT + SMB_DR_LOOKUP_SID, + SMB_DR_LOOKUP_NAME }; enum smb_kdr_opcode_t { diff --git a/usr/src/uts/common/smbsrv/smb_fsops.h b/usr/src/uts/common/smbsrv/smb_fsops.h index afed8b6637..07e825c24d 100644 --- a/usr/src/uts/common/smbsrv/smb_fsops.h +++ b/usr/src/uts/common/smbsrv/smb_fsops.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,11 +36,15 @@ #include <smbsrv/smbinfo.h> #include <smbsrv/smb_vops.h> #include <smbsrv/smbvar.h> +#include <sys/callb.h> +#include <sys/flock.h> #ifdef __cplusplus extern "C" { #endif +extern caller_context_t smb_ct; + int smb_fsop_open(smb_ofile_t *of); int smb_fsop_close(smb_ofile_t *of); @@ -119,7 +123,13 @@ int smb_fsop_sdread(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *); int smb_fsop_sdwrite(smb_request_t *, cred_t *, smb_node_t *, smb_fssd_t *, int); -void smb_get_caller_context(smb_request_t *sr, caller_context_t *ct); +uint32_t smb_fsop_shrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid, + uint32_t desired_access, uint32_t share_access); + +void smb_fsop_unshrlock(cred_t *cr, smb_node_t *node, uint32_t uniq_fid); + +int smb_fsop_frlock(smb_request_t *sr, smb_node_t *node, smb_lock_t *lock, + boolean_t unlock); /* * Lookup-related flags diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 0b9442bed1..a23b42572c 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -101,10 +101,12 @@ void smb_release_oplock(struct smb_ofile *file, int reason); uint32_t smb_unlock_range(struct smb_request *, struct smb_node *, uint64_t, uint64_t); -void smb_unlock_range_raise_error(smb_request_t *sr, uint32_t ntstatus); uint32_t smb_lock_range(struct smb_request *, struct smb_ofile *, uint64_t, uint64_t, uint32_t, uint32_t); -void smb_lock_range_raise_error(smb_request_t *sr, uint32_t ntstatus); +void smb_lock_range_error(smb_request_t *, uint32_t); + +DWORD smb_range_check(smb_request_t *, cred_t *, smb_node_t *, + uint64_t, uint64_t, boolean_t); int smb_mangle_name(ino64_t fileid, char *name, char *shortname, char *name83, int force); @@ -149,31 +151,17 @@ void smbsr_decode_error(struct smb_request *); void smbsr_encode_error(struct smb_request *); void smbsr_encode_empty_result(struct smb_request *sr); -#pragma does_not_return(smbsr_decode_error) -#pragma does_not_return(smbsr_encode_error) - int smbsr_decode_vwv(struct smb_request *sr, char *fmt, ...); int smbsr_decode_data(struct smb_request *sr, char *fmt, ...); void smbsr_encode_result(struct smb_request *, int, int, char *, ...); smb_xa_t *smbsr_lookup_xa(smb_request_t *sr); void smbsr_send_reply(struct smb_request *); -void smbsr_raise_cifs_error(struct smb_request *sr, DWORD status, - int error_class, int error_code); - -int smbsr_set_errno(struct smb_request *, int); -void smbsr_raise_errno(struct smb_request *, int); -void smbsr_raise_error(struct smb_request *, int, int); -void smbsr_raise_nt_error(struct smb_request *sr, uint32_t); - -#pragma does_not_return(smbsr_raise_cifs_error) -#pragma does_not_return(smbsr_raise_error) -#pragma does_not_return(smbsr_raise_nt_error) -#pragma does_not_return(smbsr_raise_errno) - -void smbsr_setup_nt_status(struct smb_request *sr, - uint32_t severity, - uint32_t nt_status); +void smbsr_map_errno(int, smb_error_t *); +void smbsr_set_error(smb_request_t *, smb_error_t *); +void smbsr_errno(struct smb_request *, int); +void smbsr_warn(struct smb_request *, DWORD, uint16_t, uint16_t); +void smbsr_error(struct smb_request *, DWORD, uint16_t, uint16_t); int smb_mbc_encode(struct mbuf_chain *mbc, char *fmt, va_list ap); int smb_mbc_decode(struct mbuf_chain *mbc, char *fmt, va_list ap); @@ -202,7 +190,7 @@ 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, uint32_t desired_access); + uint64_t, uint64_t, boolean_t); uint32_t smb_decode_sd(struct smb_xa *, smb_sd_t *); @@ -247,6 +235,17 @@ void smb_node_root_fini(); void smb_node_add_lock(smb_node_t *node, smb_lock_t *lock); void smb_node_destroy_lock(smb_node_t *node, smb_lock_t *lock); void smb_node_destroy_lock_by_ofile(smb_node_t *node, smb_ofile_t *file); +void smb_node_start_crit(smb_node_t *node, krw_t mode); +void smb_node_end_crit(smb_node_t *node); +int smb_node_in_crit(smb_node_t *node); + +uint32_t smb_node_open_check(smb_node_t *, cred_t *, + uint32_t, uint32_t); +uint32_t smb_node_share_check(smb_node_t *, cred_t *, + uint32_t, uint32_t, smb_ofile_t *); +DWORD smb_node_rename_check(smb_node_t *); +DWORD smb_node_delete_check(smb_node_t *); + uint64_t smb_node_get_size(smb_node_t *node, smb_attr_t *attr); void smb_node_set_time(struct smb_node *node, timestruc_t *crtime, timestruc_t *mtime, timestruc_t *atime, @@ -359,7 +358,6 @@ int smb_stream_parse_name(char *name, char *u_stream_name, uint32_t smb_get_gmtoff(void); void smb_set_gmtoff(uint32_t); -void smb_errmap_unix2smb(int en, smb_error_t *smberr); DWORD smb_trans2_set_information(struct smb_request *sr, smb_trans2_setinfo_t *info, smb_error_t *smberr); @@ -398,7 +396,8 @@ void smb_session_disconnect_volume(fs_desc_t *); smb_ofile_t *smb_ofile_lookup_by_fid(smb_tree_t *tree, uint16_t fid); smb_ofile_t *smb_ofile_open(smb_tree_t *tree, smb_node_t *node, uint16_t pid, uint32_t access_granted, uint32_t create_options, uint32_t share_access, - uint16_t ftype, char *pipe_name, uint32_t rpc_fid, smb_error_t *err); + uint16_t ftype, char *pipe_name, uint32_t rpc_fid, uint32_t uniqid, + smb_error_t *err); int smb_ofile_close(smb_ofile_t *ofile, uint32_t last_wtime); uint32_t smb_ofile_access(smb_ofile_t *ofile, cred_t *cr, uint32_t access); int smb_ofile_seek(smb_ofile_t *of, ushort_t mode, int32_t off, diff --git a/usr/src/uts/common/smbsrv/smb_privilege.h b/usr/src/uts/common/smbsrv/smb_privilege.h index c03455d469..9fad667938 100644 --- a/usr/src/uts/common/smbsrv/smb_privilege.h +++ b/usr/src/uts/common/smbsrv/smb_privilege.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -98,6 +98,7 @@ extern "C" { #define SE_CHANGE_NOTIFY_NAME "SeChangeNotifyPrivilege" #define SE_REMOTE_SHUTDOWN_NAME "SeRemoteShutdownPrivilege" +#define SE_MIN_LUID 2 #define SE_CREATE_TOKEN_LUID 2 #define SE_ASSIGNPRIMARYTOKEN_LUID 3 #define SE_LOCK_MEMORY_LUID 4 @@ -121,6 +122,7 @@ extern "C" { #define SE_SYSTEM_ENVIRONMENT_LUID 22 #define SE_CHANGE_NOTIFY_LUID 23 #define SE_REMOTE_SHUTDOWN_LUID 24 +#define SE_MAX_LUID 24 /* * Privilege attributes @@ -181,6 +183,7 @@ int smb_privset_size(); void smb_privset_init(smb_privset_t *privset); void smb_privset_free(smb_privset_t *privset); void smb_privset_copy(smb_privset_t *dst, smb_privset_t *src); +void smb_privset_merge(smb_privset_t *dst, smb_privset_t *src); void smb_privset_enable(smb_privset_t *privset, uint32_t id); int smb_privset_query(smb_privset_t *privset, uint32_t id); void smb_privset_log(smb_privset_t *privset); diff --git a/usr/src/uts/common/smbsrv/smb_vops.h b/usr/src/uts/common/smbsrv/smb_vops.h index 3b09c99b63..0f98b41be5 100644 --- a/usr/src/uts/common/smbsrv/smb_vops.h +++ b/usr/src/uts/common/smbsrv/smb_vops.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -318,67 +318,53 @@ struct fs_stream_info { int fhopen(const struct smb_node *, int); -extern int smb_vop_open(vnode_t **vpp, int mode, cred_t *cred, - caller_context_t *ct); -extern int smb_vop_close(vnode_t *vp, int flag, cred_t *cred, - caller_context_t *ct); -extern int smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_write(vnode_t *vp, uio_t *uiop, unsigned int *flag, - uint32_t *lcount, cred_t *cr, caller_context_t *ct); -extern int smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, - smb_attr_t *ret_attr, int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, - smb_attr_t *set_attr, int flags, cred_t *cr, boolean_t no_xvattr, - caller_context_t *ct); -extern int smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, - cred_t *cr); -extern void smb_vop_eaccess(vnode_t *vp, int *mode, int flags, vnode_t *dir_vp, - cred_t *cr); -extern int smb_vop_lookup(vnode_t *dvp, char *name, vnode_t **vpp, - char *od_name, int flags, vnode_t *rootvp, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_create(vnode_t *dvp, char *name, smb_attr_t *attr, - vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct, - vsecattr_t *vsap); -extern int smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_rename(vnode_t *from_dvp, char *from_name, vnode_t *to_dvp, - char *to_name, int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_mkdir(vnode_t *dvp, char *name, smb_attr_t *attr, - vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct, - vsecattr_t *vsap); -extern int smb_vop_rmdir(vnode_t *dvp, char *name, int flags, cred_t *cr, - caller_context_t *ct); -extern 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, caller_context_t *ct); -extern int smb_vop_commit(vnode_t *vp, cred_t *cr, caller_context_t *ct); -extern int smb_vop_getdents(struct smb_node *dir_snode, uint32_t *cookiep, - uint64_t *verifierp, int32_t *dircountp, char *arg, char *pattern, - uint32_t flags, struct smb_request *sr, cred_t *cr, - caller_context_t *ct); -extern int smb_vop_statfs(vnode_t *vp, struct statvfs64 *statp, cred_t *cr); -extern int smb_vop_stream_lookup(vnode_t *fvp, char *stream_name, - vnode_t **vpp, char *name, vnode_t **xattrdirvpp, int flags, - vnode_t *rootvp, cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_create(vnode_t *fvp, char *stream_name, - smb_attr_t *attr, vnode_t **vpp, vnode_t **xattrdirvpp, int flags, - cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, - cred_t *cr, caller_context_t *ct); -extern int smb_vop_stream_readdir(vnode_t *fvp, uint32_t *cookiep, - struct fs_stream_info *stream_info, vnode_t **vpp, vnode_t **xattrdirvp, - int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_lookup_xattrdir(vnode_t *fvp, vnode_t **xattrdirvpp, - int flags, cred_t *cr, caller_context_t *ct); -extern int smb_vop_traverse_check(vnode_t **vpp); - -int smb_vop_acl_read(vnode_t *vp, acl_t **aclp, int flags, acl_type_t acl_type, - cred_t *cr, caller_context_t *ct); -int smb_vop_acl_write(vnode_t *vp, acl_t *aclp, int flags, cred_t *cr, - caller_context_t *ct); -acl_type_t smb_vop_acl_type(vnode_t *vp); +extern void smb_vop_start(void); +extern int smb_vop_open(vnode_t **, int, cred_t *); +extern int smb_vop_close(vnode_t *, int, cred_t *); +extern int smb_vop_read(vnode_t *, uio_t *, cred_t *); +extern int smb_vop_write(vnode_t *, uio_t *, unsigned int *, + uint32_t *, cred_t *); +extern int smb_vop_getattr(vnode_t *, vnode_t *, + smb_attr_t *, int, cred_t *); +extern int smb_vop_setattr(vnode_t *, vnode_t *, + smb_attr_t *, int, cred_t *, boolean_t); +extern int smb_vop_access(vnode_t *, int, int, vnode_t *, + cred_t *); +extern void smb_vop_eaccess(vnode_t *, int *, int, vnode_t *, + cred_t *); +extern int smb_vop_lookup(vnode_t *, char *, vnode_t **, + char *, int, vnode_t *, cred_t *); +extern int smb_vop_create(vnode_t *, char *, smb_attr_t *, + vnode_t **, int, cred_t *, vsecattr_t *); +extern int smb_vop_remove(vnode_t *, char *, int, cred_t *); +extern int smb_vop_rename(vnode_t *, char *, vnode_t *, + char *, int, cred_t *); +extern int smb_vop_mkdir(vnode_t *, char *, smb_attr_t *, + vnode_t **, int, cred_t *, vsecattr_t *); +extern int smb_vop_rmdir(vnode_t *, char *, int, cred_t *); +extern int smb_vop_readdir(vnode_t *, uint32_t *, char *, + int *, ino64_t *, vnode_t **, char *, int, cred_t *); +extern int smb_vop_commit(vnode_t *, cred_t *); +extern int smb_vop_getdents(struct smb_node *, uint32_t *, + uint64_t *, int32_t *, char *, char *, + uint32_t, struct smb_request *, cred_t *); +extern int smb_vop_statfs(vnode_t *, struct statvfs64 *, cred_t *); +extern int smb_vop_stream_lookup(vnode_t *, char *, + vnode_t **, char *, vnode_t **, int, vnode_t *, cred_t *); +extern int smb_vop_stream_create(vnode_t *, char *, + smb_attr_t *, vnode_t **, vnode_t **, int, cred_t *); +extern int smb_vop_stream_remove(vnode_t *, char *, int, cred_t *); +extern int smb_vop_stream_readdir(vnode_t *, uint32_t *, + struct fs_stream_info *, vnode_t **, vnode_t **, int, cred_t *); +extern int smb_vop_lookup_xattrdir(vnode_t *, vnode_t **, int, cred_t *); +extern int smb_vop_traverse_check(vnode_t **); + +int smb_vop_acl_read(vnode_t *, acl_t **, int, acl_type_t, cred_t *); +int smb_vop_acl_write(vnode_t *, acl_t *, int, cred_t *); +acl_type_t smb_vop_acl_type(vnode_t *); + +int smb_vop_shrlock(vnode_t *, uint32_t, uint32_t, uint32_t, cred_t *); +int smb_vop_unshrlock(vnode_t *, uint32_t, cred_t *); #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smbinfo.h b/usr/src/uts/common/smbsrv/smbinfo.h index 2426b54b61..01404f3a55 100644 --- a/usr/src/uts/common/smbsrv/smbinfo.h +++ b/usr/src/uts/common/smbsrv/smbinfo.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -127,18 +127,17 @@ typedef struct smb_kmod_cfg { uint32_t skc_maxworkers; uint32_t skc_maxconnections; uint32_t skc_keepalive; - uint32_t skc_restrict_anon; - uint32_t skc_signing_enable; - uint32_t skc_signing_required; - uint32_t skc_signing_check; - uint32_t skc_oplock_enable; uint32_t skc_oplock_timeout; - uint32_t skc_flush_required; - uint32_t skc_sync_enable; - uint32_t skc_dirsymlink_enable; - uint32_t skc_announce_quota; - uint32_t skc_secmode; - uint32_t skc_lmlevel; + int32_t skc_restrict_anon; + int32_t skc_signing_enable; + int32_t skc_signing_required; + int32_t skc_signing_check; + int32_t skc_oplock_enable; + int32_t skc_flush_required; + int32_t skc_sync_enable; + int32_t skc_dirsymlink_enable; + int32_t skc_announce_quota; + int32_t skc_secmode; char skc_resource_domain[SMB_PI_MAX_DOMAIN]; char skc_hostname[SMB_PI_MAX_HOST]; @@ -173,7 +172,6 @@ int smbnative_pdc_value(char *native_lm); #define SMBD_DOOR_PARAM_GET 2 #define SMBD_DOOR_PARAM_SET 3 #define SMBD_DOOR_NETBIOS_RECONFIG 4 -#define SMBD_DOOR_ADS_DOMAIN_CHANGED 5 #ifdef __cplusplus } diff --git a/usr/src/uts/common/smbsrv/smbvar.h b/usr/src/uts/common/smbsrv/smbvar.h index edcfbe7187..f4e11582a0 100644 --- a/usr/src/uts/common/smbsrv/smbvar.h +++ b/usr/src/uts/common/smbsrv/smbvar.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -389,6 +389,7 @@ typedef enum { typedef struct smb_node { uint32_t n_magic; smb_rwx_t n_lock; + krwlock_t n_share_lock; list_node_t n_lnd; smb_node_state_t n_state; uint32_t n_refcnt; @@ -835,6 +836,7 @@ typedef struct smb_ofile { mlsvc_pipe_t *f_pipe_info; + uint32_t f_uniqid; uint32_t f_refcnt; uint64_t f_seek_pos; uint32_t f_flags; @@ -1198,11 +1200,8 @@ struct smb_request { label_t exjb; cred_t *user_cr; - caller_context_t ct; }; -caller_context_t local_ct; - #define SMB_READ_PROTOCOL(smb_nh_ptr) \ LE_IN32(((smb_nethdr_t *)(smb_nh_ptr))->sh_protocol) @@ -1317,6 +1316,7 @@ typedef struct smb_info { volatile uint64_t si_global_kid; volatile uint32_t si_gmtoff; + volatile uint32_t si_uniq_fid; smb_thread_t si_nbt_daemon; smb_thread_t si_tcp_daemon; @@ -1354,11 +1354,13 @@ typedef struct smb_info { #define SMB_INFO_ENCRYPT_PASSWORDS 0x80000000 #define SMB_NEW_KID() atomic_inc_64_nv(&smb_info.si_global_kid) +#define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_info.si_uniq_fid) typedef struct { + uint32_t severity; + uint32_t status; uint16_t errcls; uint16_t errcode; - DWORD status; } smb_error_t; /* |