I know we're supposed to be feature frozen, but I couldn't resist this... :-).
authorJeremy Allison <jra@samba.org>
Wed, 4 Apr 2001 23:42:17 +0000 (23:42 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 4 Apr 2001 23:42:17 +0000 (23:42 +0000)
I worked out and added the per-share get/set RPCs for security descriptors.
Currently this code returns Everyone, full access on get and permission denied
on set, but backending this with a tdb and checking it on tconX (to give full NT
semantics for security on shares) is now an excersise for the reader... :-).
Jeremy.
(This used to be commit 3bfd155ba78798c50588904d4ea3389f50f8abb6)

source3/include/proto.h
source3/include/rpc_srvsvc.h
source3/rpc_parse/parse_srv.c
source3/rpc_server/srv_srvsvc.c
source3/rpc_server/srv_srvsvc_nt.c

index 69aabab485afde7de90d079e1a21f51c3547c1ac..3af984788c83e62814e19a1128886b9d375fc1b8 100644 (file)
@@ -3494,6 +3494,13 @@ void init_srv_share_info2(SH_INFO_2 *sh2,
                                char *net_name, uint32 type, char *remark,
                                uint32 perms, uint32 max_uses, uint32 num_uses,
                                char *path, char *passwd);
+void init_srv_share_info502(SH_INFO_502 *sh502,
+                               char *net_name, uint32 type, char *remark,
+                               uint32 perms, uint32 max_uses, uint32 num_uses,
+                               char *path, char *passwd, SEC_DESC *psd, size_t sd_size);
+void init_srv_share_info502_str(SH_INFO_502_STR *sh502,
+                               char *net_name, char *remark,
+                               char *path, char *passwd, SEC_DESC *psd, size_t sd_size);
 void init_srv_q_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n, 
                                char *srv_name, uint32 info_level,
                                uint32 preferred_len, ENUM_HND *hnd);
@@ -3501,6 +3508,8 @@ BOOL srv_io_q_net_share_enum(char *desc, SRV_Q_NET_SHARE_ENUM *q_n, prs_struct *
 BOOL srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *ps, int depth);
 BOOL srv_io_q_net_share_get_info(char *desc, SRV_Q_NET_SHARE_GET_INFO *q_n, prs_struct *ps, int depth);
 BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_struct *ps, int depth);
+BOOL srv_io_q_net_share_set_info(char *desc, SRV_Q_NET_SHARE_SET_INFO *q_n, prs_struct *ps, int depth);
+BOOL srv_io_r_net_share_set_info(char *desc, SRV_R_NET_SHARE_SET_INFO *q_n, prs_struct *ps, int depth);
 void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, char *name);
 void init_srv_sess_info0(SESS_INFO_0 *ss0, char *name);
 void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, char *name, char *user);
@@ -3773,6 +3782,7 @@ uint32 _srv_net_conn_enum(pipes_struct *p, SRV_Q_NET_CONN_ENUM *q_u, SRV_R_NET_C
 uint32 _srv_net_sess_enum(pipes_struct *p, SRV_Q_NET_SESS_ENUM *q_u, SRV_R_NET_SESS_ENUM *r_u);
 uint32 _srv_net_share_enum(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R_NET_SHARE_ENUM *r_u);
 uint32 _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, SRV_R_NET_SHARE_GET_INFO *r_u);
+uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u);
 uint32 _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET_REMOTE_TOD *r_u);
 
 /*The following definitions come from  rpc_server/srv_util.c  */
index b18c70bf258a89663b0b72ccda1fe2aac9a0615f..dcf466fbe3510ad8a14ae56992b7e612a478f06f 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    Unix SMB/Netbios implementation.
    Version 1.9.
    SMB parameters and setup
@@ -31,6 +31,7 @@
 #define SRV_NETSESSENUM        0x0c
 #define SRV_NETSHAREENUM       0x0f
 #define SRV_NET_SHARE_GET_INFO 0x10
+#define SRV_NET_SHARE_SET_INFO 0x11
 #define SRV_NET_SRV_GET_INFO   0x15
 #define SRV_NET_SRV_SET_INFO   0x16
 #define SRV_NET_REMOTE_TOD     0x1c
@@ -305,6 +306,44 @@ typedef struct share_info_2_info
 
 } SRV_SHARE_INFO_2;
 
+/* SH_INFO_502 (pointers to level 502 share info strings) */
+typedef struct ptr_share_info502
+{
+       uint32 ptr_netname; /* pointer to net name. */
+       uint32 type; /* ipc, print, disk ... */
+       uint32 ptr_remark; /* pointer to comment. */
+       uint32 perms;      /* permissions */
+       uint32 max_uses;   /* maximum uses */
+       uint32 num_uses;   /* current uses */
+       uint32 ptr_path;   /* pointer to path name */
+       uint32 ptr_passwd; /* pointer to password */
+       uint32 sd_size;    /* size of security descriptor */
+       uint32 ptr_sd;     /* pointer to security descriptor */
+
+} SH_INFO_502;
+
+/* SH_INFO_502_STR (level 502 share info strings) */
+typedef struct str_share_info502
+{
+       UNISTR2 uni_netname; /* unicode string of net name (e.g NETLOGON) */
+       UNISTR2 uni_remark;  /* unicode string of comment (e.g "Logon server share") */
+       UNISTR2 uni_path;    /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */
+       UNISTR2 uni_passwd;  /* unicode string of password - presumably for share level security (e.g NULL) */
+
+       uint32 sd_size;
+       SEC_DESC *sd;
+
+} SH_INFO_502_STR;
+
+/* SRV_SHARE_INFO_502 */
+/* SRV_SHARE_INFO_2 */
+typedef struct share_info_502_info
+{
+       SH_INFO_502 info_502;
+       SH_INFO_502_STR info_502_str;
+
+} SRV_SHARE_INFO_502;
+
 /* SRV_SHARE_INFO_1005 */
 typedef struct share_info_1005_info
 {
@@ -325,6 +364,7 @@ typedef struct srv_share_info_ctr_info
        union {
                SRV_SHARE_INFO_1 *info1; /* share info level 1 */
                SRV_SHARE_INFO_2 *info2; /* share info level 2 */
+               SRV_SHARE_INFO_502 *info502; /* share info level 502 */
                void *info;
 
        } share;
@@ -370,22 +410,50 @@ typedef struct q_net_share_get_info_info
 
 } SRV_Q_NET_SHARE_GET_INFO;
 
-/* SRV_R_NET_SHARE_GET_INFO */
-typedef struct r_net_share_get_info_info
-{
+/* SRV_SHARE_INFO */
+typedef struct srv_share_info {
        uint32 switch_value;
        uint32 ptr_share_ctr;
 
        union {
                SRV_SHARE_INFO_1 info1;
                SRV_SHARE_INFO_2 info2;
-               SRV_SHARE_INFO_1005 info1005;
+               SRV_SHARE_INFO_502 info502;
+        SRV_SHARE_INFO_1005 info1005;
        } share;
+} SRV_SHARE_INFO;
 
+/* SRV_R_NET_SHARE_GET_INFO */
+typedef struct r_net_share_get_info_info
+{
+       SRV_SHARE_INFO info;
        uint32 status;
 
 } SRV_R_NET_SHARE_GET_INFO;
 
+/* JRA. NB. We also need level 1004, 1006 and 1501 here. */
+
+/* SRV_Q_NET_SHARE_SET_INFO */
+typedef struct q_net_share_set_info_info
+{
+       uint32 ptr_srv_name;
+       UNISTR2 uni_srv_name;
+
+       UNISTR2 uni_share_name;
+       uint32 info_level;
+
+       SRV_SHARE_INFO info;
+
+} SRV_Q_NET_SHARE_SET_INFO;
+
+/* SRV_R_NET_SHARE_SET_INFO */
+typedef struct r_net_share_set_info
+{
+       uint32 switch_value;         /* switch value */
+
+       uint32 status;               /* return status */
+
+} SRV_R_NET_SHARE_SET_INFO;
 
 /* FILE_INFO_3 (level 3 file info strings) */
 typedef struct file_info3_info
index 55a0cd95e5aec676b7d2dace9e5213ccd1b27e4f..dd70c5521c3216e20a9a94cabb7d8d3107031b65 100644 (file)
@@ -211,6 +211,132 @@ static BOOL srv_io_share_info2(char *desc, SH_INFO_2 *sh2, prs_struct *ps, int d
        return True;
 }
 
+/*******************************************************************
+ Inits a SH_INFO_502 structure
+********************************************************************/
+
+void init_srv_share_info502(SH_INFO_502 *sh502,
+                               char *net_name, uint32 type, char *remark,
+                               uint32 perms, uint32 max_uses, uint32 num_uses,
+                               char *path, char *passwd, SEC_DESC *psd, size_t sd_size)
+{
+       DEBUG(5,("init_srv_share_info502: %s %8x %s\n", net_name, type, remark));
+
+       ZERO_STRUCTP(sh502);
+
+       sh502->ptr_netname = (net_name != NULL) ? 1 : 0;
+       sh502->type        = type;
+       sh502->ptr_remark  = (remark != NULL) ? 1 : 0;
+       sh502->perms       = perms;
+       sh502->max_uses    = max_uses;
+       sh502->num_uses    = num_uses;
+       sh502->type        = type;
+       sh502->ptr_path    = (path != NULL) ? 1 : 0;
+       sh502->ptr_passwd  = (passwd != NULL) ? 1 : 0;
+       sh502->sd_size     = (uint32)sd_size;
+       sh502->ptr_sd      = (psd != NULL) ? 1 : 0;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info502(char *desc, SH_INFO_502 *sh502, prs_struct *ps, int depth)
+{
+       if (sh502 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_share_info502");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_netname", ps, depth, &sh502->ptr_netname))
+               return False;
+       if(!prs_uint32("type       ", ps, depth, &sh502->type))
+               return False;
+       if(!prs_uint32("ptr_remark ", ps, depth, &sh502->ptr_remark))
+               return False;
+       if(!prs_uint32("perms      ", ps, depth, &sh502->perms))
+               return False;
+       if(!prs_uint32("max_uses   ", ps, depth, &sh502->max_uses))
+               return False;
+       if(!prs_uint32("num_uses   ", ps, depth, &sh502->num_uses))
+               return False;
+       if(!prs_uint32("ptr_path   ", ps, depth, &sh502->ptr_path))
+               return False;
+       if(!prs_uint32("ptr_passwd ", ps, depth, &sh502->ptr_passwd))
+               return False;
+       if(!prs_uint32("sd_size    ", ps, depth, &sh502->sd_size))
+               return False;
+       if(!prs_uint32("ptr_sd     ", ps, depth, &sh502->ptr_sd))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Inits a SH_INFO_502_STR structure
+********************************************************************/
+
+void init_srv_share_info502_str(SH_INFO_502_STR *sh502,
+                               char *net_name, char *remark,
+                               char *path, char *passwd, SEC_DESC *psd, size_t sd_size)
+{
+       DEBUG(5,("init_srv_share_info502_str\n"));
+
+       init_unistr2(&sh502->uni_netname, net_name, strlen(net_name)+1);
+       init_unistr2(&sh502->uni_remark, remark, strlen(remark)+1);
+       init_unistr2(&sh502->uni_path, path, strlen(path)+1);
+       init_unistr2(&sh502->uni_passwd, passwd, strlen(passwd)+1);
+       sh502->sd = psd;
+       sh502->sd_size = sd_size;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+static BOOL srv_io_share_info502_str(char *desc, SH_INFO_502_STR *sh502, prs_struct *ps, int depth)
+{
+       if (sh502 == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_share_info502_str");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_unistr2("", &sh502->uni_netname, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_unistr2("", &sh502->uni_remark, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_unistr2("", &sh502->uni_path, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_unistr2("", &sh502->uni_passwd, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("sd_size   ", ps, depth, &sh502->sd_size))
+               return False;
+       if (!sec_io_desc(desc, &sh502->sd, ps, depth))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
  Reads or writes a structure.
 ********************************************************************/
@@ -334,6 +460,31 @@ static BOOL srv_io_srv_share_ctr(char *desc, SRV_SHARE_INFO_CTR *ctr, prs_struct
                break;
        }
 
+       case 502:
+       {
+               SRV_SHARE_INFO_502 *info502 = ctr->share.info502;
+               int num_entries = ctr->num_entries;
+               int i;
+
+               if (UNMARSHALLING(ps)) {
+                       if (!(info502 = (SRV_SHARE_INFO_502 *)prs_alloc_mem(ps,num_entries * sizeof(SRV_SHARE_INFO_502))))
+                               return False;
+                       ctr->share.info502 = info502;
+               }
+
+               for (i = 0; i < num_entries; i++) {
+                       if(!srv_io_share_info502("", &info502[i].info_502, ps, depth))
+                               return False;
+               }
+
+               for (i = 0; i < num_entries; i++) {
+                       if(!srv_io_share_info502_str("", &info502[i].info_502_str, ps, depth))
+                               return False;
+               }
+
+               break;
+       }
+
        default:
                DEBUG(5,("%s no share info at switch_value %d\n",
                         tab_depth(depth), ctr->switch_value));
@@ -462,12 +613,12 @@ BOOL srv_io_q_net_share_get_info(char *desc, SRV_Q_NET_SHARE_GET_INFO *q_n, prs_
  Reads or writes a structure.
 ********************************************************************/
 
-BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_struct *ps, int depth)
+static BOOL srv_io_srv_share_info(char *desc, prs_struct *ps, int depth, SRV_SHARE_INFO *r_n)
 {
        if (r_n == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "srv_io_r_net_share_get_info");
+       prs_debug(ps, depth, desc, "srv_io_srv_share_info");
        depth++;
 
        if(!prs_align(ps))
@@ -497,9 +648,15 @@ BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_
                                return False;
 
                        break;
+               case 502:
+                       if(!srv_io_share_info502("", &r_n->share.info502.info_502, ps, depth))
+                               return False;
+
+                       if(!srv_io_share_info502_str("", &r_n->share.info502.info_502_str, ps, depth))
+                               return False;
+                       break;
                case 1005:
-                       if(!srv_io_share_info1005("", &r_n->share.info1005, 
-                                                 ps, depth))
+                       if(!srv_io_share_info1005("", &r_n->share.info1005, ps, depth))
                                 return False;                  
                default:
                        DEBUG(5,("%s no share info at switch_value %d\n",
@@ -508,6 +665,27 @@ BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_
                }
        }
 
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_struct *ps, int depth)
+{
+       if (r_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_share_get_info");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!srv_io_srv_share_info("info  ", ps, depth, &r_n->info))
+               return False;
+
        if(!prs_align(ps))
                return False;
 
@@ -517,6 +695,67 @@ BOOL srv_io_r_net_share_get_info(char *desc, SRV_R_NET_SHARE_GET_INFO *r_n, prs_
        return True;
 }
 
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_q_net_share_set_info(char *desc, SRV_Q_NET_SHARE_SET_INFO *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_share_set_info");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+               return False;
+       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+               return False;
+
+       if(!smb_io_unistr2("", &q_n->uni_share_name, True, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("info_level", ps, depth, &q_n->info_level))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!srv_io_srv_share_info("info  ", ps, depth, &q_n->info))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_r_net_share_set_info(char *desc, SRV_R_NET_SHARE_SET_INFO *q_n, prs_struct *ps, int depth)
+{
+       if (q_n == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_r_net_share_set_info");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("switch_value  ", ps, depth, &q_n->switch_value))
+               return False;
+       if(!prs_uint32("status        ", ps, depth, &q_n->status))
+               return False;
+
+       return True;
+}      
+
 /*******************************************************************
  Inits a SESS_INFO_0_STR structure
 ********************************************************************/
index a3176bfd739c667746ec08abb91f0fb79b86d924..76e6be2ec1d4abb8a03464cb3cac651525da5b7b 100644 (file)
@@ -197,6 +197,36 @@ static BOOL api_srv_net_share_get_info(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ RPC to set share information.
+********************************************************************/
+
+static BOOL api_srv_net_share_set_info(pipes_struct *p)
+{
+       SRV_Q_NET_SHARE_SET_INFO q_u;
+       SRV_R_NET_SHARE_SET_INFO r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* Unmarshall the net server set info. */
+       if(!srv_io_q_net_share_set_info("", &q_u, data, 0)) {
+               DEBUG(0,("api_srv_net_share_set_info: Failed to unmarshall SRV_Q_NET_SHARE_SET_INFO.\n"));
+               return False;
+       }
+
+       r_u.status = _srv_net_share_set_info(p, &q_u, &r_u);
+
+       if(!srv_io_r_net_share_set_info("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_srv_net_share_set_info: Failed to marshall SRV_R_NET_SHARE_SET_INFO.\n"));
+               return False;
+       }
+
+       return True;
+}
+
 /*******************************************************************
  api_srv_net_remote_tod
 ********************************************************************/
@@ -234,6 +264,7 @@ struct api_struct api_srv_cmds[] =
        { "SRV_NETSESSENUM"       , SRV_NETSESSENUM       , api_srv_net_sess_enum    },
        { "SRV_NETSHAREENUM"      , SRV_NETSHAREENUM      , api_srv_net_share_enum   },
        { "SRV_NET_SHARE_GET_INFO", SRV_NET_SHARE_GET_INFO, api_srv_net_share_get_info },
+       { "SRV_NET_SHARE_SET_INFO", SRV_NET_SHARE_SET_INFO, api_srv_net_share_set_info },
        { "SRV_NETFILEENUM"       , SRV_NETFILEENUM       , api_srv_net_file_enum    },
        { "SRV_NET_SRV_GET_INFO"  , SRV_NET_SRV_GET_INFO  , api_srv_net_srv_get_info },
        { "SRV_NET_REMOTE_TOD"    , SRV_NET_REMOTE_TOD    , api_srv_net_remote_tod   },
index 061c70454f709d861dc593c9d6014350df4d7e90..4d6d7518bfd7f2bfc18c9c87028328d590d5e0e4 100644 (file)
@@ -93,6 +93,73 @@ static void init_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, int snum)
        init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
 }
 
+/*******************************************************************
+ Fake up a Everyone, full access for now.
+ ********************************************************************/
+
+static SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
+{
+       extern DOM_SID global_sid_World;
+       SEC_ACCESS sa;
+       SEC_ACE ace;
+       SEC_ACL *psa = NULL;
+       SEC_DESC *psd = NULL;
+
+    init_sec_access(&sa, GENERIC_ALL_ACCESS );
+    init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
+
+       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
+               psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, psize);
+       }
+
+       if (!psd) {
+               DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
+               return NULL;
+       }
+
+       return psd;
+}
+
+/*******************************************************************
+ Fill in a share info level 502 structure.
+ ********************************************************************/
+
+static void init_srv_share_info_502(TALLOC_CTX *ctx, SRV_SHARE_INFO_502 *sh502, int snum)
+{
+       int len_net_name;
+       pstring net_name;
+       pstring remark;
+       pstring path;
+       pstring passwd;
+       uint32 type;
+       SEC_DESC *sd;
+       size_t sd_size;
+
+       ZERO_STRUCTP(sh502);
+
+       pstrcpy(net_name, lp_servicename(snum));
+       pstrcpy(remark, lp_comment(snum));
+       pstring_sub(remark,"%S",lp_servicename(snum));
+       pstrcpy(path, lp_pathname(snum));
+       pstrcpy(passwd, "");
+       len_net_name = strlen(net_name);
+
+       /* work out the share type */
+       type = STYPE_DISKTREE;
+               
+       if (lp_print_ok(snum))
+               type = STYPE_PRINTQ;
+       if (strequal("IPC$", net_name))
+               type = STYPE_IPC;
+       if (net_name[len_net_name] == '$')
+               type |= STYPE_HIDDEN;
+
+       sd = get_share_security(ctx, snum, &sd_size);
+
+       init_srv_share_info502(&sh502->info_502, net_name, type, remark, 0, 0xffffffff, 1, path, passwd, sd, sd_size);
+       init_srv_share_info502_str(&sh502->info_502_str, net_name, remark, path, passwd, sd, sd_size);
+}
+
 /***************************************************************************
  Fill in a share info level 1005 structure.
  ***************************************************************************/
@@ -174,6 +241,23 @@ static BOOL init_srv_share_info_ctr(TALLOC_CTX *ctx, SRV_SHARE_INFO_CTR *ctr,
                break;
        }
 
+       case 502:
+       {
+               SRV_SHARE_INFO_502 *info502;
+               int i = 0;
+
+               info502 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_502));
+
+               for (snum = *resume_hnd; snum < num_services; snum++) {
+                       if (lp_browseable(snum) && lp_snum_ok(snum)) {
+                               init_srv_share_info_502(ctx, &info502[i++], snum);
+                       }
+               }
+
+               ctr->share.info502 = info502;
+               break;
+       }
+
        default:
                DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n", info_level));
                return False;
@@ -205,7 +289,7 @@ static void init_srv_r_net_share_enum(TALLOC_CTX *ctx, SRV_R_NET_SHARE_ENUM *r_n
  Inits a SRV_R_NET_SHARE_GET_INFO structure.
 ********************************************************************/
 
-static void init_srv_r_net_share_get_info(SRV_R_NET_SHARE_GET_INFO *r_n,
+static void init_srv_r_net_share_get_info(TALLOC_CTX *ctx, SRV_R_NET_SHARE_GET_INFO *r_n,
                                  char *share_name, uint32 info_level)
 {
        uint32 status = NT_STATUS_NOPROBLEMO;
@@ -213,20 +297,23 @@ static void init_srv_r_net_share_get_info(SRV_R_NET_SHARE_GET_INFO *r_n,
 
        DEBUG(5,("init_srv_r_net_share_get_info: %d\n", __LINE__));
 
-       r_n->switch_value = info_level;
+       r_n->info.switch_value = info_level;
 
        snum = find_service(share_name);
 
        if (snum >= 0) {
                switch (info_level) {
                case 1:
-                       init_srv_share_info_1(&r_n->share.info1, snum);
+                       init_srv_share_info_1(&r_n->info.share.info1, snum);
                        break;
                case 2:
-                       init_srv_share_info_2(&r_n->share.info2, snum);
+                       init_srv_share_info_2(&r_n->info.share.info2, snum);
+                       break;
+               case 502:
+                       init_srv_share_info_502(ctx, &r_n->info.share.info502, snum);
                        break;
                case 1005:
-                       init_srv_share_info_1005(&r_n->share.info1005, snum);
+                       init_srv_share_info_1005(&r_n->info.share.info1005, snum);
                        break;
                default:
                        DEBUG(5,("init_srv_net_share_get_info: unsupported switch value %d\n", info_level));
@@ -237,7 +324,7 @@ static void init_srv_r_net_share_get_info(SRV_R_NET_SHARE_GET_INFO *r_n,
                status = NT_STATUS_BAD_NETWORK_NAME;
        }
 
-       r_n->ptr_share_ctr = (status == NT_STATUS_NOPROBLEMO) ? 1 : 0;
+       r_n->info.ptr_share_ctr = (status == NT_STATUS_NOPROBLEMO) ? 1 : 0;
        r_n->status = status;
 }
 
@@ -815,13 +902,64 @@ uint32 _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, S
 
        /* Create the list of shares for the response. */
        share_name = dos_unistr2_to_str(&q_u->uni_share_name);
-       init_srv_r_net_share_get_info(r_u, share_name, q_u->info_level);
+       init_srv_r_net_share_get_info(p->mem_ctx, r_u, share_name, q_u->info_level);
 
        DEBUG(5,("_srv_net_share_get_info: %d\n", __LINE__));
 
        return r_u->status;
 }
 
+/*******************************************************************
+ Net share set info.
+********************************************************************/
+
+uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u)
+{
+       char *share_name;
+       uint32 status = NT_STATUS_NOPROBLEMO;
+       int snum;
+
+       DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
+
+       share_name = dos_unistr2_to_str(&q_u->uni_share_name);
+
+       r_u->switch_value = q_u->info_level;
+
+       snum = find_service(share_name);
+
+       /* For now we only handle setting the security descriptor. JRA. */
+
+       if (snum >= 0) {
+               switch (q_u->info_level) {
+               case 1:
+                       status = NT_STATUS_ACCESS_DENIED;
+                       break;
+               case 2:
+                       status = NT_STATUS_ACCESS_DENIED;
+                       break;
+               case 502:
+                       /* we set sd's here. FIXME. JRA */
+                       status = NT_STATUS_ACCESS_DENIED;
+                       break;
+               case 1005:
+                       status = NT_STATUS_ACCESS_DENIED;
+                       break;
+               default:
+                       DEBUG(5,("_srv_net_share_set_info: unsupported switch value %d\n", q_u->info_level));
+                       status = NT_STATUS_INVALID_INFO_CLASS;
+                       break;
+               }
+       } else {
+               status = NT_STATUS_BAD_NETWORK_NAME;
+       }
+
+       r_u->status = status;
+
+       DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
+
+       return r_u->status;
+}
+
 /*******************************************************************
 time of day
 ********************************************************************/