| 1 | #include <stdlib.h>
 | 
|---|
| 2 | #include <string.h>
 | 
|---|
| 3 | #include <errno.h>
 | 
|---|
| 4 | #include <popt.h>
 | 
|---|
| 5 | #include "libsmbclient.h"
 | 
|---|
| 6 | #include "get_auth_data_fn.h"
 | 
|---|
| 7 | 
 | 
|---|
| 8 | enum acl_mode
 | 
|---|
| 9 | {
 | 
|---|
| 10 |     SMB_ACL_LIST,
 | 
|---|
| 11 |     SMB_ACL_GET,
 | 
|---|
| 12 |     SMB_ACL_SET,
 | 
|---|
| 13 |     SMB_ACL_DELETE,
 | 
|---|
| 14 |     SMB_ACL_MODIFY,
 | 
|---|
| 15 |     SMB_ACL_ADD,
 | 
|---|
| 16 |     SMB_ACL_CHOWN,
 | 
|---|
| 17 |     SMB_ACL_CHGRP
 | 
|---|
| 18 | };
 | 
|---|
| 19 | 
 | 
|---|
| 20 | 
 | 
|---|
| 21 | int main(int argc, const char *argv[])
 | 
|---|
| 22 | {
 | 
|---|
| 23 |     int opt;
 | 
|---|
| 24 |     int flags;
 | 
|---|
| 25 |     int debug = 0;
 | 
|---|
| 26 |     int numeric = 0;
 | 
|---|
| 27 |     int stat_and_retry = 0;
 | 
|---|
| 28 |     int full_time_names = 0;
 | 
|---|
| 29 |     enum acl_mode mode = SMB_ACL_LIST;
 | 
|---|
| 30 |     static char *the_acl = NULL;
 | 
|---|
| 31 |     int ret;
 | 
|---|
| 32 |     char *p;
 | 
|---|
| 33 |     char *debugstr;
 | 
|---|
| 34 |     char path[1024];
 | 
|---|
| 35 |     char value[1024];
 | 
|---|
| 36 |     poptContext pc;
 | 
|---|
| 37 |     struct stat st;
 | 
|---|
| 38 |     struct poptOption long_options[] =
 | 
|---|
| 39 |         {
 | 
|---|
| 40 |             POPT_AUTOHELP
 | 
|---|
| 41 |             {
 | 
|---|
| 42 |                 "numeric", 'n', POPT_ARG_NONE, &numeric,
 | 
|---|
| 43 |                 1, "Don't resolve sids or masks to names"
 | 
|---|
| 44 |             },
 | 
|---|
| 45 |             {
 | 
|---|
| 46 |                 "debug", 'd', POPT_ARG_INT, &debug,
 | 
|---|
| 47 |                 0, "Set debug level (0-100)"
 | 
|---|
| 48 |             },
 | 
|---|
| 49 |             {
 | 
|---|
| 50 |                 "full_time_names", 'f', POPT_ARG_NONE, &full_time_names,
 | 
|---|
| 51 |                 1,
 | 
|---|
| 52 |                 "Use new style xattr names, which include CREATE_TIME"
 | 
|---|
| 53 |             },
 | 
|---|
| 54 |             {
 | 
|---|
| 55 |                 "delete", 'D', POPT_ARG_STRING, NULL,
 | 
|---|
| 56 |                 'D', "Delete an acl", "ACL"
 | 
|---|
| 57 |             },
 | 
|---|
| 58 |             {
 | 
|---|
| 59 |                 "modify", 'M', POPT_ARG_STRING, NULL,
 | 
|---|
| 60 |                 'M', "Modify an acl", "ACL"
 | 
|---|
| 61 |             },
 | 
|---|
| 62 |             {
 | 
|---|
| 63 |                 "add", 'a', POPT_ARG_STRING, NULL,
 | 
|---|
| 64 |                 'a', "Add an acl", "ACL"
 | 
|---|
| 65 |             },
 | 
|---|
| 66 |             {
 | 
|---|
| 67 |                 "set", 'S', POPT_ARG_STRING, NULL,
 | 
|---|
| 68 |                 'S', "Set acls", "ACLS"
 | 
|---|
| 69 |             },
 | 
|---|
| 70 |             {
 | 
|---|
| 71 |                 "chown", 'C', POPT_ARG_STRING, NULL,
 | 
|---|
| 72 |                 'C', "Change ownership of a file", "USERNAME"
 | 
|---|
| 73 |             },
 | 
|---|
| 74 |             {
 | 
|---|
| 75 |                 "chgrp", 'G', POPT_ARG_STRING, NULL,
 | 
|---|
| 76 |                 'G', "Change group ownership of a file", "GROUPNAME"
 | 
|---|
| 77 |             },
 | 
|---|
| 78 |             {
 | 
|---|
| 79 |                 "get", 'g', POPT_ARG_STRING, NULL,
 | 
|---|
| 80 |                 'g', "Get a specific acl attribute", "ACL"
 | 
|---|
| 81 |             },
 | 
|---|
| 82 |             {
 | 
|---|
| 83 |                 "stat_and_retry", 'R', POPT_ARG_NONE, &stat_and_retry,
 | 
|---|
| 84 |                 1, "After 'get' do 'stat' and another 'get'"
 | 
|---|
| 85 |             },
 | 
|---|
| 86 |             {
 | 
|---|
| 87 |                 NULL
 | 
|---|
| 88 |             }
 | 
|---|
| 89 |         };
 | 
|---|
| 90 |     
 | 
|---|
| 91 |     setbuf(stdout, NULL);
 | 
|---|
| 92 | 
 | 
|---|
| 93 |     pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
 | 
|---|
| 94 |     
 | 
|---|
| 95 |     poptSetOtherOptionHelp(pc, "smb://server1/share1/filename");
 | 
|---|
| 96 |     
 | 
|---|
| 97 |     while ((opt = poptGetNextOpt(pc)) != -1) {
 | 
|---|
| 98 |         switch (opt) {
 | 
|---|
| 99 |         case 'S':
 | 
|---|
| 100 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 101 |             mode = SMB_ACL_SET;
 | 
|---|
| 102 |             break;
 | 
|---|
| 103 |             
 | 
|---|
| 104 |         case 'D':
 | 
|---|
| 105 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 106 |             mode = SMB_ACL_DELETE;
 | 
|---|
| 107 |             break;
 | 
|---|
| 108 |             
 | 
|---|
| 109 |         case 'M':
 | 
|---|
| 110 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 111 |             mode = SMB_ACL_MODIFY;
 | 
|---|
| 112 |             break;
 | 
|---|
| 113 |             
 | 
|---|
| 114 |         case 'a':
 | 
|---|
| 115 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 116 |             mode = SMB_ACL_ADD;
 | 
|---|
| 117 |             break;
 | 
|---|
| 118 | 
 | 
|---|
| 119 |         case 'g':
 | 
|---|
| 120 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 121 |             mode = SMB_ACL_GET;
 | 
|---|
| 122 |             break;
 | 
|---|
| 123 | 
 | 
|---|
| 124 |         case 'C':
 | 
|---|
| 125 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 126 |             mode = SMB_ACL_CHOWN;
 | 
|---|
| 127 |             break;
 | 
|---|
| 128 | 
 | 
|---|
| 129 |         case 'G':
 | 
|---|
| 130 |             the_acl = strdup(poptGetOptArg(pc));
 | 
|---|
| 131 |             mode = SMB_ACL_CHGRP;
 | 
|---|
| 132 |             break;
 | 
|---|
| 133 |         }
 | 
|---|
| 134 |     }
 | 
|---|
| 135 |     
 | 
|---|
| 136 |     /* Make connection to server */
 | 
|---|
| 137 |     if(!poptPeekArg(pc)) { 
 | 
|---|
| 138 |         poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 139 |         return 1;
 | 
|---|
| 140 |     }
 | 
|---|
| 141 |     
 | 
|---|
| 142 |     strcpy(path, poptGetArg(pc));
 | 
|---|
| 143 |     
 | 
|---|
| 144 |     if (smbc_init(get_auth_data_fn, debug) != 0)
 | 
|---|
| 145 |     {
 | 
|---|
| 146 |         printf("Could not initialize smbc_ library\n");
 | 
|---|
| 147 |         return 1;
 | 
|---|
| 148 |     }
 | 
|---|
| 149 | 
 | 
|---|
| 150 |     if (full_time_names) {
 | 
|---|
| 151 |         SMBCCTX *context = smbc_set_context(NULL);
 | 
|---|
| 152 |         smbc_setOptionFullTimeNames(context, 1);
 | 
|---|
| 153 |     }
 | 
|---|
| 154 |     
 | 
|---|
| 155 |     /* Perform requested action */
 | 
|---|
| 156 |     
 | 
|---|
| 157 |     switch(mode)
 | 
|---|
| 158 |     {
 | 
|---|
| 159 |     case SMB_ACL_LIST:
 | 
|---|
| 160 |         ret = smbc_listxattr(path, value, sizeof(value)-2);
 | 
|---|
| 161 |         if (ret < 0)
 | 
|---|
| 162 |         {
 | 
|---|
| 163 |             printf("Could not get attribute list for [%s] %d: %s\n",
 | 
|---|
| 164 |                    path, errno, strerror(errno));
 | 
|---|
| 165 |             return 1;
 | 
|---|
| 166 |         }
 | 
|---|
| 167 | 
 | 
|---|
| 168 |         /*
 | 
|---|
| 169 |          * The list of attributes has a series of null-terminated strings.
 | 
|---|
| 170 |          * The list of strings terminates with an extra null byte, thus two in
 | 
|---|
| 171 |          * a row.  Ensure that our buffer, which is conceivably shorter than
 | 
|---|
| 172 |          * the list of attributes, actually ends with two null bytes in a row.
 | 
|---|
| 173 |          */
 | 
|---|
| 174 |         value[sizeof(value) - 2] = '\0';
 | 
|---|
| 175 |         value[sizeof(value) - 1] = '\0';
 | 
|---|
| 176 |         printf("Supported attributes:\n");
 | 
|---|
| 177 |         for (p = value; *p; p += strlen(p) + 1)
 | 
|---|
| 178 |         {
 | 
|---|
| 179 |             printf("\t%s\n", p);
 | 
|---|
| 180 |         }
 | 
|---|
| 181 |         break;
 | 
|---|
| 182 | 
 | 
|---|
| 183 |     case SMB_ACL_GET:
 | 
|---|
| 184 |         do
 | 
|---|
| 185 |         {
 | 
|---|
| 186 |             if (the_acl == NULL)
 | 
|---|
| 187 |             {
 | 
|---|
| 188 |                 if (numeric)
 | 
|---|
| 189 |                 {
 | 
|---|
| 190 |                     the_acl = "system.*";
 | 
|---|
| 191 |                 }
 | 
|---|
| 192 |                 else
 | 
|---|
| 193 |                 {
 | 
|---|
| 194 |                     the_acl = "system.*+";
 | 
|---|
| 195 |                 }
 | 
|---|
| 196 |             }
 | 
|---|
| 197 |             ret = smbc_getxattr(path, the_acl, value, sizeof(value));
 | 
|---|
| 198 |             if (ret < 0)
 | 
|---|
| 199 |             {
 | 
|---|
| 200 |                 printf("Could not get attributes for [%s] %d: %s\n",
 | 
|---|
| 201 |                        path, errno, strerror(errno));
 | 
|---|
| 202 |                 return 1;
 | 
|---|
| 203 |             }
 | 
|---|
| 204 |         
 | 
|---|
| 205 |             printf("Attributes for [%s] are:\n%s\n", path, value);
 | 
|---|
| 206 | 
 | 
|---|
| 207 |             if (stat_and_retry)
 | 
|---|
| 208 |             {
 | 
|---|
| 209 |                 if (smbc_stat(path, &st) < 0)
 | 
|---|
| 210 |                 {
 | 
|---|
| 211 |                     perror("smbc_stat");
 | 
|---|
| 212 |                     return 1;
 | 
|---|
| 213 |                 }
 | 
|---|
| 214 |             }
 | 
|---|
| 215 | 
 | 
|---|
| 216 |             --stat_and_retry;
 | 
|---|
| 217 |         } while (stat_and_retry >= 0);
 | 
|---|
| 218 |         break;
 | 
|---|
| 219 | 
 | 
|---|
| 220 |     case SMB_ACL_ADD:
 | 
|---|
| 221 |         flags = SMBC_XATTR_FLAG_CREATE;
 | 
|---|
| 222 |         debugstr = "add attributes";
 | 
|---|
| 223 |         goto do_set;
 | 
|---|
| 224 |         
 | 
|---|
| 225 |     case SMB_ACL_MODIFY:
 | 
|---|
| 226 |         flags = SMBC_XATTR_FLAG_REPLACE;
 | 
|---|
| 227 |         debugstr = "modify attributes";
 | 
|---|
| 228 |         goto do_set;
 | 
|---|
| 229 | 
 | 
|---|
| 230 |     case SMB_ACL_CHOWN:
 | 
|---|
| 231 |         snprintf(value, sizeof(value),
 | 
|---|
| 232 |                  "system.nt_sec_desc.owner%s:%s",
 | 
|---|
| 233 |                  numeric ? "" : "+", the_acl);
 | 
|---|
| 234 |         the_acl = value;
 | 
|---|
| 235 |         debugstr = "chown owner";
 | 
|---|
| 236 |         goto do_set;
 | 
|---|
| 237 | 
 | 
|---|
| 238 |     case SMB_ACL_CHGRP:
 | 
|---|
| 239 |         snprintf(value, sizeof(value),
 | 
|---|
| 240 |                  "system.nt_sec_desc.group%s:%s",
 | 
|---|
| 241 |                  numeric ? "" : "+", the_acl);
 | 
|---|
| 242 |         the_acl = value;
 | 
|---|
| 243 |         debugstr = "change group";
 | 
|---|
| 244 |         goto do_set;
 | 
|---|
| 245 | 
 | 
|---|
| 246 |     case SMB_ACL_SET:
 | 
|---|
| 247 |         flags = 0;
 | 
|---|
| 248 |         debugstr = "set attributes";
 | 
|---|
| 249 |         
 | 
|---|
| 250 |       do_set:
 | 
|---|
| 251 |         if ((p = strchr(the_acl, ':')) == NULL)
 | 
|---|
| 252 |         {
 | 
|---|
| 253 |             printf("Missing value.  ACL must be name:value pair\n");
 | 
|---|
| 254 |             return 1;
 | 
|---|
| 255 |         }
 | 
|---|
| 256 | 
 | 
|---|
| 257 |         *p++ = '\0';
 | 
|---|
| 258 |         
 | 
|---|
| 259 |         ret = smbc_setxattr(path, the_acl, p, strlen(p), flags);
 | 
|---|
| 260 |         if (ret < 0)
 | 
|---|
| 261 |         {
 | 
|---|
| 262 |             printf("Could not %s for [%s] %d: %s\n",
 | 
|---|
| 263 |                    debugstr, path, errno, strerror(errno));
 | 
|---|
| 264 |             return 1;
 | 
|---|
| 265 |         }
 | 
|---|
| 266 |         break;
 | 
|---|
| 267 | 
 | 
|---|
| 268 |     case SMB_ACL_DELETE:
 | 
|---|
| 269 |         ret = smbc_removexattr(path, the_acl);
 | 
|---|
| 270 |         if (ret < 0)
 | 
|---|
| 271 |         {
 | 
|---|
| 272 |             printf("Could not remove attribute %s for [%s] %d:%s\n",
 | 
|---|
| 273 |                    the_acl, path, errno, strerror(errno));
 | 
|---|
| 274 |             return 1;
 | 
|---|
| 275 |         }
 | 
|---|
| 276 |         break;
 | 
|---|
| 277 | 
 | 
|---|
| 278 |     default:
 | 
|---|
| 279 |         printf("operation not yet implemented\n");
 | 
|---|
| 280 |         break;
 | 
|---|
| 281 |     }
 | 
|---|
| 282 |     
 | 
|---|
| 283 |     return 0;
 | 
|---|
| 284 | }
 | 
|---|