#include <stdlib.h> #include <string.h> #include <errno.h> #include <popt.h> #include "libsmbclient.h" enum acl_mode { SMB_ACL_GET, SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD, SMB_ACL_CHOWN, SMB_ACL_CHGRP }; static void get_auth_data_fn(const char * pServer, const char * pShare, char * pWorkgroup, int maxLenWorkgroup, char * pUsername, int maxLenUsername, char * pPassword, int maxLenPassword) { char temp[128]; fprintf(stdout, "Workgroup: [%s] ", pWorkgroup); fgets(temp, sizeof(temp), stdin); if (temp[strlen(temp) - 1] == '\n') /* A new line? */ { temp[strlen(temp) - 1] = '\0'; } if (temp[0] != '\0') { strncpy(pWorkgroup, temp, maxLenWorkgroup - 1); } fprintf(stdout, "Username: [%s] ", pUsername); fgets(temp, sizeof(temp), stdin); if (temp[strlen(temp) - 1] == '\n') /* A new line? */ { temp[strlen(temp) - 1] = '\0'; } if (temp[0] != '\0') { strncpy(pUsername, temp, maxLenUsername - 1); } fprintf(stdout, "Password: "); fgets(temp, sizeof(temp), stdin); if (temp[strlen(temp) - 1] == '\n') /* A new line? */ { temp[strlen(temp) - 1] = '\0'; } if (temp[0] != '\0') { strncpy(pPassword, temp, maxLenPassword - 1); } } int main(int argc, const char *argv[]) { int opt; int flags; int debug = 0; int numeric = 0; enum acl_mode mode = SMB_ACL_GET; static char *the_acl = NULL; int ret; char *p; char *debugstr; char path[1024]; char value[1024]; poptContext pc; struct poptOption long_options[] = { POPT_AUTOHELP { "numeric", 'n', POPT_ARG_NONE, &numeric, 1, "Don't resolve sids or masks to names" }, { "debug", 'd', POPT_ARG_INT, &debug, 0, "Set debug level (0-100)" }, { "delete", 'D', POPT_ARG_STRING, NULL, 'D', "Delete an acl", "ACL" }, { "modify", 'M', POPT_ARG_STRING, NULL, 'M', "Modify an acl", "ACL" }, { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an acl", "ACL" }, { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" }, { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" }, { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" }, { "get", 'g', POPT_ARG_STRING, NULL, 'g', "Get a specific acl attribute", "ACL" }, { NULL } }; setbuf(stdout, NULL); pc = poptGetContext("smbcacls", argc, argv, long_options, 0); poptSetOtherOptionHelp(pc, "smb://server1/share1/filename"); while ((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'S': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_SET; break; case 'D': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_DELETE; break; case 'M': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_MODIFY; break; case 'a': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_ADD; break; case 'g': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_GET; break; case 'C': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_CHOWN; break; case 'G': the_acl = strdup(poptGetOptArg(pc)); mode = SMB_ACL_CHGRP; break; } } /* Make connection to server */ if(!poptPeekArg(pc)) { poptPrintUsage(pc, stderr, 0); return 1; } strcpy(path, poptGetArg(pc)); if (smbc_init(get_auth_data_fn, debug) != 0) { printf("Could not initialize smbc_ library\n"); return 1; } /* Perform requested action */ switch(mode) { case SMB_ACL_GET: if (the_acl == NULL) { if (numeric) { the_acl = "system.nt_sec_desc.*"; } else { the_acl = "system.nt_sec_desc.*+"; } } ret = smbc_getxattr(path, the_acl, value, sizeof(value)); if (ret < 0) { printf("Could not get attributes for [%s] %d: %s\n", path, errno, strerror(errno)); return 1; } printf("Attributes for [%s] are:\n%s\n", path, value); break; case SMB_ACL_ADD: flags = SMBC_XATTR_FLAG_CREATE; debugstr = "add attributes"; goto do_set; case SMB_ACL_MODIFY: flags = SMBC_XATTR_FLAG_REPLACE; debugstr = "modify attributes"; goto do_set; case SMB_ACL_CHOWN: snprintf(value, sizeof(value), "system.nt_sec_desc.owner%s:%s", numeric ? "" : "+", the_acl); the_acl = value; debugstr = "chown owner"; goto do_set; case SMB_ACL_CHGRP: snprintf(value, sizeof(value), "system.nt_sec_desc.group%s:%s", numeric ? "" : "+", the_acl); the_acl = value; debugstr = "change group"; goto do_set; case SMB_ACL_SET: flags = 0; debugstr = "set attributes"; do_set: if ((p = strchr(the_acl, ':')) == NULL) { printf("Missing value. ACL must be name:value pair\n"); return 1; } *p++ = '\0'; ret = smbc_setxattr(path, the_acl, p, strlen(p), flags); if (ret < 0) { printf("Could not %s for [%s] %d: %s\n", debugstr, path, errno, strerror(errno)); return 1; } break; case SMB_ACL_DELETE: ret = smbc_removexattr(path, the_acl); if (ret < 0) { printf("Could not remove attribute %s for [%s] %d:%s\n", the_acl, path, errno, strerror(errno)); return 1; } break; default: printf("operation not yet implemented\n"); break; } return 0; }