utils/smbcacls.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    ACL get/set utility
00004    
00005    Copyright (C) Andrew Tridgell 2000
00006    Copyright (C) Tim Potter      2000
00007    Copyright (C) Jeremy Allison  2000
00008    Copyright (C) Jelmer Vernooij 2003
00009    
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 
00027 static pstring owner_username;
00028 static fstring server;
00029 static int test_args = False;
00030 static TALLOC_CTX *ctx;
00031 
00032 #define CREATE_ACCESS_READ READ_CONTROL_ACCESS
00033 
00034 /* numeric is set when the user wants numeric SIDs and ACEs rather
00035    than going via LSA calls to resolve them */
00036 static BOOL numeric = False;
00037 
00038 enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
00039 enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP};
00040 enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
00041 
00042 struct perm_value {
00043         const char *perm;
00044         uint32 mask;
00045 };
00046 
00047 /* These values discovered by inspection */
00048 
00049 static const struct perm_value special_values[] = {
00050         { "R", 0x00120089 },
00051         { "W", 0x00120116 },
00052         { "X", 0x001200a0 },
00053         { "D", 0x00010000 },
00054         { "P", 0x00040000 },
00055         { "O", 0x00080000 },
00056         { NULL, 0 },
00057 };
00058 
00059 static const struct perm_value standard_values[] = {
00060         { "READ",   0x001200a9 },
00061         { "CHANGE", 0x001301bf },
00062         { "FULL",   0x001f01ff },
00063         { NULL, 0 },
00064 };
00065 
00066 static struct cli_state *global_hack_cli;
00067 static struct rpc_pipe_client *global_pipe_hnd;
00068 static POLICY_HND pol;
00069 static BOOL got_policy_hnd;
00070 
00071 static struct cli_state *connect_one(const char *share);
00072 
00073 /* Open cli connection and policy handle */
00074 
00075 static BOOL cacls_open_policy_hnd(void)
00076 {
00077         /* Initialise cli LSA connection */
00078 
00079         if (!global_hack_cli) {
00080                 NTSTATUS ret;
00081                 global_hack_cli = connect_one("IPC$");
00082                 global_pipe_hnd = cli_rpc_pipe_open_noauth(global_hack_cli, PI_LSARPC, &ret);
00083                 if (!global_pipe_hnd) {
00084                                 return False;
00085                 }
00086         }
00087         
00088         /* Open policy handle */
00089 
00090         if (!got_policy_hnd) {
00091 
00092                 /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
00093                    but NT sends 0x2000000 so we might as well do it too. */
00094 
00095                 if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, global_hack_cli->mem_ctx, True, 
00096                                                          GENERIC_EXECUTE_ACCESS, &pol))) {
00097                         return False;
00098                 }
00099 
00100                 got_policy_hnd = True;
00101         }
00102         
00103         return True;
00104 }
00105 
00106 /* convert a SID to a string, either numeric or username/group */
00107 static void SidToString(fstring str, DOM_SID *sid)
00108 {
00109         char **domains = NULL;
00110         char **names = NULL;
00111         enum lsa_SidType *types = NULL;
00112 
00113         sid_to_string(str, sid);
00114 
00115         if (numeric) return;
00116 
00117         /* Ask LSA to convert the sid to a name */
00118 
00119         if (!cacls_open_policy_hnd() ||
00120             !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, global_hack_cli->mem_ctx,  
00121                                                  &pol, 1, sid, &domains, 
00122                                                  &names, &types)) ||
00123             !domains || !domains[0] || !names || !names[0]) {
00124                 return;
00125         }
00126 
00127         /* Converted OK */
00128 
00129         slprintf(str, sizeof(fstring) - 1, "%s%s%s",
00130                  domains[0], lp_winbind_separator(),
00131                  names[0]);
00132         
00133 }
00134 
00135 /* convert a string to a SID, either numeric or username/group */
00136 static BOOL StringToSid(DOM_SID *sid, const char *str)
00137 {
00138         enum lsa_SidType *types = NULL;
00139         DOM_SID *sids = NULL;
00140         BOOL result = True;
00141 
00142         if (strncmp(str, "S-", 2) == 0) {
00143                 return string_to_sid(sid, str);
00144         }
00145 
00146         if (!cacls_open_policy_hnd() ||
00147             !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, 
00148                                                   &pol, 1, &str, NULL, &sids, 
00149                                                   &types))) {
00150                 result = False;
00151                 goto done;
00152         }
00153 
00154         sid_copy(sid, &sids[0]);
00155  done:
00156 
00157         return result;
00158 }
00159 
00160 
00161 /* print an ACE on a FILE, using either numeric or ascii representation */
00162 static void print_ace(FILE *f, SEC_ACE *ace)
00163 {
00164         const struct perm_value *v;
00165         fstring sidstr;
00166         int do_print = 0;
00167         uint32 got_mask;
00168 
00169         SidToString(sidstr, &ace->trustee);
00170 
00171         fprintf(f, "%s:", sidstr);
00172 
00173         if (numeric) {
00174                 fprintf(f, "%d/%d/0x%08x", 
00175                         ace->type, ace->flags, ace->access_mask);
00176                 return;
00177         }
00178 
00179         /* Ace type */
00180 
00181         if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED) {
00182                 fprintf(f, "ALLOWED");
00183         } else if (ace->type == SEC_ACE_TYPE_ACCESS_DENIED) {
00184                 fprintf(f, "DENIED");
00185         } else {
00186                 fprintf(f, "%d", ace->type);
00187         }
00188 
00189         /* Not sure what flags can be set in a file ACL */
00190 
00191         fprintf(f, "/%d/", ace->flags);
00192 
00193         /* Standard permissions */
00194 
00195         for (v = standard_values; v->perm; v++) {
00196                 if (ace->access_mask == v->mask) {
00197                         fprintf(f, "%s", v->perm);
00198                         return;
00199                 }
00200         }
00201 
00202         /* Special permissions.  Print out a hex value if we have
00203            leftover bits in the mask. */
00204 
00205         got_mask = ace->access_mask;
00206 
00207  again:
00208         for (v = special_values; v->perm; v++) {
00209                 if ((ace->access_mask & v->mask) == v->mask) {
00210                         if (do_print) {
00211                                 fprintf(f, "%s", v->perm);
00212                         }
00213                         got_mask &= ~v->mask;
00214                 }
00215         }
00216 
00217         if (!do_print) {
00218                 if (got_mask != 0) {
00219                         fprintf(f, "0x%08x", ace->access_mask);
00220                 } else {
00221                         do_print = 1;
00222                         goto again;
00223                 }
00224         }
00225 }
00226 
00227 
00228 /* parse an ACE in the same format as print_ace() */
00229 static BOOL parse_ace(SEC_ACE *ace, const char *orig_str)
00230 {
00231         char *p;
00232         const char *cp;
00233         fstring tok;
00234         unsigned int atype = 0;
00235         unsigned int aflags = 0;
00236         unsigned int amask = 0;
00237         DOM_SID sid;
00238         SEC_ACCESS mask;
00239         const struct perm_value *v;
00240         char *str = SMB_STRDUP(orig_str);
00241 
00242         if (!str) {
00243                 return False;
00244         }
00245 
00246         ZERO_STRUCTP(ace);
00247         p = strchr_m(str,':');
00248         if (!p) {
00249                 printf("ACE '%s': missing ':'.\n", orig_str);
00250                 SAFE_FREE(str);
00251                 return False;
00252         }
00253         *p = '\0';
00254         p++;
00255         /* Try to parse numeric form */
00256 
00257         if (sscanf(p, "%i/%i/%i", &atype, &aflags, &amask) == 3 &&
00258             StringToSid(&sid, str)) {
00259                 goto done;
00260         }
00261 
00262         /* Try to parse text form */
00263 
00264         if (!StringToSid(&sid, str)) {
00265                 printf("ACE '%s': failed to convert '%s' to SID\n",
00266                         orig_str, str);
00267                 SAFE_FREE(str);
00268                 return False;
00269         }
00270 
00271         cp = p;
00272         if (!next_token(&cp, tok, "/", sizeof(fstring))) {
00273                 printf("ACE '%s': failed to find '/' character.\n",
00274                         orig_str);
00275                 SAFE_FREE(str);
00276                 return False;
00277         }
00278 
00279         if (strncmp(tok, "ALLOWED", strlen("ALLOWED")) == 0) {
00280                 atype = SEC_ACE_TYPE_ACCESS_ALLOWED;
00281         } else if (strncmp(tok, "DENIED", strlen("DENIED")) == 0) {
00282                 atype = SEC_ACE_TYPE_ACCESS_DENIED;
00283         } else {
00284                 printf("ACE '%s': missing 'ALLOWED' or 'DENIED' entry at '%s'\n",
00285                         orig_str, tok);
00286                 SAFE_FREE(str);
00287                 return False;
00288         }
00289 
00290         /* Only numeric form accepted for flags at present */
00291 
00292         if (!(next_token(&cp, tok, "/", sizeof(fstring)) &&
00293               sscanf(tok, "%i", &aflags))) {
00294                 printf("ACE '%s': bad integer flags entry at '%s'\n",
00295                         orig_str, tok);
00296                 SAFE_FREE(str);
00297                 return False;
00298         }
00299 
00300         if (!next_token(&cp, tok, "/", sizeof(fstring))) {
00301                 printf("ACE '%s': missing / at '%s'\n",
00302                         orig_str, tok);
00303                 SAFE_FREE(str);
00304                 return False;
00305         }
00306 
00307         if (strncmp(tok, "0x", 2) == 0) {
00308                 if (sscanf(tok, "%i", &amask) != 1) {
00309                         printf("ACE '%s': bad hex number at '%s'\n",
00310                                 orig_str, tok);
00311                         SAFE_FREE(str);
00312                         return False;
00313                 }
00314                 goto done;
00315         }
00316 
00317         for (v = standard_values; v->perm; v++) {
00318                 if (strcmp(tok, v->perm) == 0) {
00319                         amask = v->mask;
00320                         goto done;
00321                 }
00322         }
00323 
00324         p = tok;
00325 
00326         while(*p) {
00327                 BOOL found = False;
00328 
00329                 for (v = special_values; v->perm; v++) {
00330                         if (v->perm[0] == *p) {
00331                                 amask |= v->mask;
00332                                 found = True;
00333                         }
00334                 }
00335 
00336                 if (!found) {
00337                         printf("ACE '%s': bad permission value at '%s'\n",
00338                                 orig_str, p);
00339                         SAFE_FREE(str);
00340                         return False;
00341                 }
00342                 p++;
00343         }
00344 
00345         if (*p) {
00346                 SAFE_FREE(str);
00347                 return False;
00348         }
00349 
00350  done:
00351         mask = amask;
00352         init_sec_ace(ace, &sid, atype, mask, aflags);
00353         SAFE_FREE(str);
00354         return True;
00355 }
00356 
00357 /* add an ACE to a list of ACEs in a SEC_ACL */
00358 static BOOL add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
00359 {
00360         SEC_ACL *new_ace;
00361         SEC_ACE *aces;
00362         if (! *the_acl) {
00363                 return (((*the_acl) = make_sec_acl(ctx, 3, 1, ace)) != NULL);
00364         }
00365 
00366         if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) {
00367                 return False;
00368         }
00369         memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
00370         memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
00371         new_ace = make_sec_acl(ctx,(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
00372         SAFE_FREE(aces);
00373         (*the_acl) = new_ace;
00374         return True;
00375 }
00376 
00377 /* parse a ascii version of a security descriptor */
00378 static SEC_DESC *sec_desc_parse(char *str)
00379 {
00380         const char *p = str;
00381         fstring tok;
00382         SEC_DESC *ret = NULL;
00383         size_t sd_size;
00384         DOM_SID *group_sid=NULL, *owner_sid=NULL;
00385         SEC_ACL *dacl=NULL;
00386         int revision=1;
00387 
00388         while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) {
00389 
00390                 if (strncmp(tok,"REVISION:", 9) == 0) {
00391                         revision = strtol(tok+9, NULL, 16);
00392                         continue;
00393                 }
00394 
00395                 if (strncmp(tok,"OWNER:", 6) == 0) {
00396                         if (owner_sid) {
00397                                 printf("Only specify owner once\n");
00398                                 goto done;
00399                         }
00400                         owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
00401                         if (!owner_sid ||
00402                             !StringToSid(owner_sid, tok+6)) {
00403                                 printf("Failed to parse owner sid\n");
00404                                 goto done;
00405                         }
00406                         continue;
00407                 }
00408 
00409                 if (strncmp(tok,"GROUP:", 6) == 0) {
00410                         if (group_sid) {
00411                                 printf("Only specify group once\n");
00412                                 goto done;
00413                         }
00414                         group_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
00415                         if (!group_sid ||
00416                             !StringToSid(group_sid, tok+6)) {
00417                                 printf("Failed to parse group sid\n");
00418                                 goto done;
00419                         }
00420                         continue;
00421                 }
00422 
00423                 if (strncmp(tok,"ACL:", 4) == 0) {
00424                         SEC_ACE ace;
00425                         if (!parse_ace(&ace, tok+4)) {
00426                                 goto done;
00427                         }
00428                         if(!add_ace(&dacl, &ace)) {
00429                                 printf("Failed to add ACL %s\n", tok);
00430                                 goto done;
00431                         }
00432                         continue;
00433                 }
00434 
00435                 printf("Failed to parse token '%s' in security descriptor,\n", tok);
00436                 goto done;
00437         }
00438 
00439         ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, group_sid, 
00440                             NULL, dacl, &sd_size);
00441 
00442   done:
00443         SAFE_FREE(group_sid);
00444         SAFE_FREE(owner_sid);
00445 
00446         return ret;
00447 }
00448 
00449 
00450 /* print a ascii version of a security descriptor on a FILE handle */
00451 static void sec_desc_print(FILE *f, SEC_DESC *sd)
00452 {
00453         fstring sidstr;
00454         uint32 i;
00455 
00456         fprintf(f, "REVISION:%d\n", sd->revision);
00457 
00458         /* Print owner and group sid */
00459 
00460         if (sd->owner_sid) {
00461                 SidToString(sidstr, sd->owner_sid);
00462         } else {
00463                 fstrcpy(sidstr, "");
00464         }
00465 
00466         fprintf(f, "OWNER:%s\n", sidstr);
00467 
00468         if (sd->group_sid) {
00469                 SidToString(sidstr, sd->group_sid);
00470         } else {
00471                 fstrcpy(sidstr, "");
00472         }
00473 
00474         fprintf(f, "GROUP:%s\n", sidstr);
00475 
00476         /* Print aces */
00477         for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
00478                 SEC_ACE *ace = &sd->dacl->aces[i];
00479                 fprintf(f, "ACL:");
00480                 print_ace(f, ace);
00481                 fprintf(f, "\n");
00482         }
00483 
00484 }
00485 
00486 /***************************************************** 
00487 dump the acls for a file
00488 *******************************************************/
00489 static int cacl_dump(struct cli_state *cli, char *filename)
00490 {
00491         int result = EXIT_FAILED;
00492         int fnum = -1;
00493         SEC_DESC *sd;
00494 
00495         if (test_args) 
00496                 return EXIT_OK;
00497 
00498         fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
00499 
00500         if (fnum == -1) {
00501                 printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
00502                 goto done;
00503         }
00504 
00505         sd = cli_query_secdesc(cli, fnum, ctx);
00506 
00507         if (!sd) {
00508                 printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
00509                 goto done;
00510         }
00511 
00512         sec_desc_print(stdout, sd);
00513 
00514         result = EXIT_OK;
00515 
00516 done:
00517         if (fnum != -1)
00518                 cli_close(cli, fnum);
00519 
00520         return result;
00521 }
00522 
00523 /***************************************************** 
00524 Change the ownership or group ownership of a file. Just
00525 because the NT docs say this can't be done :-). JRA.
00526 *******************************************************/
00527 
00528 static int owner_set(struct cli_state *cli, enum chown_mode change_mode, 
00529                      char *filename, char *new_username)
00530 {
00531         int fnum;
00532         DOM_SID sid;
00533         SEC_DESC *sd, *old;
00534         size_t sd_size;
00535 
00536         fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
00537 
00538         if (fnum == -1) {
00539                 printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
00540                 return EXIT_FAILED;
00541         }
00542 
00543         if (!StringToSid(&sid, new_username))
00544                 return EXIT_PARSE_ERROR;
00545 
00546         old = cli_query_secdesc(cli, fnum, ctx);
00547 
00548         cli_close(cli, fnum);
00549 
00550         if (!old) {
00551                 printf("owner_set: Failed to query old descriptor\n");
00552                 return EXIT_FAILED;
00553         }
00554 
00555         sd = make_sec_desc(ctx,old->revision, old->type,
00556                                 (change_mode == REQUEST_CHOWN) ? &sid : NULL,
00557                                 (change_mode == REQUEST_CHGRP) ? &sid : NULL,
00558                            NULL, NULL, &sd_size);
00559 
00560         fnum = cli_nt_create(cli, filename, WRITE_OWNER_ACCESS);
00561 
00562         if (fnum == -1) {
00563                 printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
00564                 return EXIT_FAILED;
00565         }
00566 
00567         if (!cli_set_secdesc(cli, fnum, sd)) {
00568                 printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
00569         }
00570 
00571         cli_close(cli, fnum);
00572 
00573         return EXIT_OK;
00574 }
00575 
00576 
00577 /* The MSDN is contradictory over the ordering of ACE entries in an ACL.
00578    However NT4 gives a "The information may have been modified by a
00579    computer running Windows NT 5.0" if denied ACEs do not appear before
00580    allowed ACEs. */
00581 
00582 static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
00583 {
00584         if (sec_ace_equal(ace1, ace2)) 
00585                 return 0;
00586 
00587         if (ace1->type != ace2->type) 
00588                 return ace2->type - ace1->type;
00589 
00590         if (sid_compare(&ace1->trustee, &ace2->trustee)) 
00591                 return sid_compare(&ace1->trustee, &ace2->trustee);
00592 
00593         if (ace1->flags != ace2->flags) 
00594                 return ace1->flags - ace2->flags;
00595 
00596         if (ace1->access_mask != ace2->access_mask) 
00597                 return ace1->access_mask - ace2->access_mask;
00598 
00599         if (ace1->size != ace2->size) 
00600                 return ace1->size - ace2->size;
00601 
00602         return memcmp(ace1, ace2, sizeof(SEC_ACE));
00603 }
00604 
00605 static void sort_acl(SEC_ACL *the_acl)
00606 {
00607         uint32 i;
00608         if (!the_acl) return;
00609 
00610         qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare);
00611 
00612         for (i=1;i<the_acl->num_aces;) {
00613                 if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
00614                         int j;
00615                         for (j=i; j<the_acl->num_aces-1; j++) {
00616                                 the_acl->aces[j] = the_acl->aces[j+1];
00617                         }
00618                         the_acl->num_aces--;
00619                 } else {
00620                         i++;
00621                 }
00622         }
00623 }
00624 
00625 /***************************************************** 
00626 set the ACLs on a file given an ascii description
00627 *******************************************************/
00628 static int cacl_set(struct cli_state *cli, char *filename, 
00629                     char *the_acl, enum acl_mode mode)
00630 {
00631         int fnum;
00632         SEC_DESC *sd, *old;
00633         uint32 i, j;
00634         size_t sd_size;
00635         int result = EXIT_OK;
00636 
00637         sd = sec_desc_parse(the_acl);
00638 
00639         if (!sd) return EXIT_PARSE_ERROR;
00640         if (test_args) return EXIT_OK;
00641 
00642         /* The desired access below is the only one I could find that works
00643            with NT4, W2KP and Samba */
00644 
00645         fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
00646 
00647         if (fnum == -1) {
00648                 printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
00649                 return EXIT_FAILED;
00650         }
00651 
00652         old = cli_query_secdesc(cli, fnum, ctx);
00653 
00654         if (!old) {
00655                 printf("calc_set: Failed to query old descriptor\n");
00656                 return EXIT_FAILED;
00657         }
00658 
00659         cli_close(cli, fnum);
00660 
00661         /* the logic here is rather more complex than I would like */
00662         switch (mode) {
00663         case SMB_ACL_DELETE:
00664                 for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
00665                         BOOL found = False;
00666 
00667                         for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
00668                                 if (sec_ace_equal(&sd->dacl->aces[i],
00669                                                   &old->dacl->aces[j])) {
00670                                         uint32 k;
00671                                         for (k=j; k<old->dacl->num_aces-1;k++) {
00672                                                 old->dacl->aces[k] = old->dacl->aces[k+1];
00673                                         }
00674                                         old->dacl->num_aces--;
00675                                         found = True;
00676                                         break;
00677                                 }
00678                         }
00679 
00680                         if (!found) {
00681                                 printf("ACL for ACE:"); 
00682                                 print_ace(stdout, &sd->dacl->aces[i]);
00683                                 printf(" not found\n");
00684                         }
00685                 }
00686                 break;
00687 
00688         case SMB_ACL_MODIFY:
00689                 for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
00690                         BOOL found = False;
00691 
00692                         for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
00693                                 if (sid_equal(&sd->dacl->aces[i].trustee,
00694                                               &old->dacl->aces[j].trustee)) {
00695                                         old->dacl->aces[j] = sd->dacl->aces[i];
00696                                         found = True;
00697                                 }
00698                         }
00699 
00700                         if (!found) {
00701                                 fstring str;
00702 
00703                                 SidToString(str, &sd->dacl->aces[i].trustee);
00704                                 printf("ACL for SID %s not found\n", str);
00705                         }
00706                 }
00707 
00708                 if (sd->owner_sid) {
00709                         old->owner_sid = sd->owner_sid;
00710                 }
00711 
00712                 if (sd->group_sid) { 
00713                         old->group_sid = sd->group_sid;
00714                 }
00715 
00716                 break;
00717 
00718         case SMB_ACL_ADD:
00719                 for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
00720                         add_ace(&old->dacl, &sd->dacl->aces[i]);
00721                 }
00722                 break;
00723 
00724         case SMB_ACL_SET:
00725                 old = sd;
00726                 break;
00727         }
00728 
00729         /* Denied ACE entries must come before allowed ones */
00730         sort_acl(old->dacl);
00731 
00732         /* Create new security descriptor and set it */
00733 
00734         /* We used to just have "WRITE_DAC_ACCESS" without WRITE_OWNER.
00735            But if we're sending an owner, even if it's the same as the one
00736            that already exists then W2K3 insists we open with WRITE_OWNER access.
00737            I need to check that setting a SD with no owner set works against WNT
00738            and W2K. JRA.
00739         */
00740 
00741         sd = make_sec_desc(ctx,old->revision, old->type, old->owner_sid, old->group_sid,
00742                            NULL, old->dacl, &sd_size);
00743 
00744         fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS);
00745 
00746         if (fnum == -1) {
00747                 printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
00748                 return EXIT_FAILED;
00749         }
00750 
00751         if (!cli_set_secdesc(cli, fnum, sd)) {
00752                 printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
00753                 result = EXIT_FAILED;
00754         }
00755 
00756         /* Clean up */
00757 
00758         cli_close(cli, fnum);
00759 
00760         return result;
00761 }
00762 
00763 
00764 /***************************************************** 
00765 return a connection to a server
00766 *******************************************************/
00767 static struct cli_state *connect_one(const char *share)
00768 {
00769         struct cli_state *c;
00770         struct in_addr ip;
00771         NTSTATUS nt_status;
00772         zero_ip(&ip);
00773         
00774         if (!cmdline_auth_info.got_pass) {
00775                 char *pass = getpass("Password: ");
00776                 if (pass) {
00777                         pstrcpy(cmdline_auth_info.password, pass);
00778                         cmdline_auth_info.got_pass = True;
00779                 }
00780         }
00781 
00782         if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server, 
00783                                                             &ip, 0,
00784                                                             share, "?????",  
00785                                                             cmdline_auth_info.username, lp_workgroup(),
00786                                                             cmdline_auth_info.password,
00787                                                             cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
00788                                                             cmdline_auth_info.signing_state, NULL))) {
00789                 return c;
00790         } else {
00791                 DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
00792                 return NULL;
00793         }
00794 }
00795 
00796 /****************************************************************************
00797   main program
00798 ****************************************************************************/
00799  int main(int argc, const char *argv[])
00800 {
00801         char *share;
00802         int opt;
00803         enum acl_mode mode = SMB_ACL_SET;
00804         static char *the_acl = NULL;
00805         enum chown_mode change_mode = REQUEST_NONE;
00806         int result;
00807         fstring path;
00808         pstring filename;
00809         poptContext pc;
00810         struct poptOption long_options[] = {
00811                 POPT_AUTOHELP
00812                 { "delete", 'D', POPT_ARG_STRING, NULL, 'D', "Delete an acl", "ACL" },
00813                 { "modify", 'M', POPT_ARG_STRING, NULL, 'M', "Modify an acl", "ACL" },
00814                 { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an acl", "ACL" },
00815                 { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" },
00816                 { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" },
00817                 { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" },
00818                 { "numeric", 0, POPT_ARG_NONE, &numeric, True, "Don't resolve sids or masks to names" },
00819                 { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"},
00820                 POPT_COMMON_SAMBA
00821                 POPT_COMMON_CREDENTIALS
00822                 { NULL }
00823         };
00824 
00825         struct cli_state *cli;
00826 
00827         load_case_tables();
00828 
00829         ctx=talloc_init("main");
00830 
00831         /* set default debug level to 1 regardless of what smb.conf sets */
00832         setup_logging( "smbcacls", True );
00833         DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
00834         dbf = x_stderr;
00835         x_setbuf( x_stderr, NULL );
00836 
00837         setlinebuf(stdout);
00838 
00839         lp_load(dyn_CONFIGFILE,True,False,False,True);
00840         load_interfaces();
00841 
00842         pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
00843         
00844         poptSetOtherOptionHelp(pc, "//server1/share1 filename\nACLs look like: "
00845                 "'ACL:user:[ALLOWED|DENIED]/flags/permissions'");
00846 
00847         while ((opt = poptGetNextOpt(pc)) != -1) {
00848                 switch (opt) {
00849                 case 'S':
00850                         the_acl = smb_xstrdup(poptGetOptArg(pc));
00851                         mode = SMB_ACL_SET;
00852                         break;
00853 
00854                 case 'D':
00855                         the_acl = smb_xstrdup(poptGetOptArg(pc));
00856                         mode = SMB_ACL_DELETE;
00857                         break;
00858 
00859                 case 'M':
00860                         the_acl = smb_xstrdup(poptGetOptArg(pc));
00861                         mode = SMB_ACL_MODIFY;
00862                         break;
00863 
00864                 case 'a':
00865                         the_acl = smb_xstrdup(poptGetOptArg(pc));
00866                         mode = SMB_ACL_ADD;
00867                         break;
00868 
00869                 case 'C':
00870                         pstrcpy(owner_username,poptGetOptArg(pc));
00871                         change_mode = REQUEST_CHOWN;
00872                         break;
00873 
00874                 case 'G':
00875                         pstrcpy(owner_username,poptGetOptArg(pc));
00876                         change_mode = REQUEST_CHGRP;
00877                         break;
00878                 }
00879         }
00880 
00881         /* Make connection to server */
00882         if(!poptPeekArg(pc)) { 
00883                 poptPrintUsage(pc, stderr, 0);
00884                 return -1;
00885         }
00886         
00887         fstrcpy(path, poptGetArg(pc));
00888         
00889         if(!poptPeekArg(pc)) { 
00890                 poptPrintUsage(pc, stderr, 0);  
00891                 return -1;
00892         }
00893         
00894         pstrcpy(filename, poptGetArg(pc));
00895 
00896         all_string_sub(path,"/","\\",0);
00897 
00898         fstrcpy(server,path+2);
00899         share = strchr_m(server,'\\');
00900         if (!share) {
00901                 share = strchr_m(server,'/');
00902                 if (!share) {
00903                         printf("Invalid argument: %s\n", share);
00904                         return -1;
00905                 }
00906         }
00907 
00908         *share = 0;
00909         share++;
00910 
00911         if (!test_args) {
00912                 cli = connect_one(share);
00913                 if (!cli) {
00914                         talloc_destroy(ctx);
00915                         exit(EXIT_FAILED);
00916                 }
00917         } else {
00918                 exit(0);
00919         }
00920 
00921         all_string_sub(filename, "/", "\\", 0);
00922         if (filename[0] != '\\') {
00923                 pstring s;
00924                 s[0] = '\\';
00925                 safe_strcpy(&s[1], filename, sizeof(pstring)-2);
00926                 pstrcpy(filename, s);
00927         }
00928 
00929         /* Perform requested action */
00930 
00931         if (change_mode != REQUEST_NONE) {
00932                 result = owner_set(cli, change_mode, filename, owner_username);
00933         } else if (the_acl) {
00934                 result = cacl_set(cli, filename, the_acl, mode);
00935         } else {
00936                 result = cacl_dump(cli, filename);
00937         }
00938 
00939         talloc_destroy(ctx);
00940 
00941         return result;
00942 }

Sambaに対してSat Aug 29 21:23:30 2009に生成されました。  doxygen 1.4.7