root/source3/utils/smbcquotas.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cli_open_policy_hnd
  2. SidToString
  3. StringToSid
  4. parse_quota_set
  5. do_quota
  6. connect_one
  7. main

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    QUOTA get/set utility
   4    
   5    Copyright (C) Andrew Tridgell                2000
   6    Copyright (C) Tim Potter                     2000
   7    Copyright (C) Jeremy Allison                 2000
   8    Copyright (C) Stefan (metze) Metzmacher      2003
   9    
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 
  26 static char *server;
  27 
  28 /* numeric is set when the user wants numeric SIDs and ACEs rather
  29    than going via LSA calls to resolve them */
  30 static bool numeric;
  31 static bool verbose;
  32 
  33 enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA};
  34 enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
  35 
  36 static struct cli_state *cli_ipc;
  37 static struct rpc_pipe_client *global_pipe_hnd;
  38 static struct policy_handle pol;
  39 static bool got_policy_hnd;
  40 static struct user_auth_info *smbcquotas_auth_info;
  41 
  42 static struct cli_state *connect_one(const char *share);
  43 
  44 /* Open cli connection and policy handle */
  45 
  46 static bool cli_open_policy_hnd(void)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         /* Initialise cli LSA connection */
  49 
  50         if (!cli_ipc) {
  51                 NTSTATUS ret;
  52                 cli_ipc = connect_one("IPC$");
  53                 ret = cli_rpc_pipe_open_noauth(cli_ipc,
  54                                                &ndr_table_lsarpc.syntax_id,
  55                                                &global_pipe_hnd);
  56                 if (!NT_STATUS_IS_OK(ret)) {
  57                                 return False;
  58                 }
  59         }
  60 
  61         /* Open policy handle */
  62 
  63         if (!got_policy_hnd) {
  64 
  65                 /* Some systems don't support SEC_FLAG_MAXIMUM_ALLOWED,
  66                    but NT sends 0x2000000 so we might as well do it too. */
  67 
  68                 if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, talloc_tos(), True, 
  69                                                          GENERIC_EXECUTE_ACCESS, &pol))) {
  70                         return False;
  71                 }
  72 
  73                 got_policy_hnd = True;
  74         }
  75         
  76         return True;
  77 }
  78 
  79 /* convert a SID to a string, either numeric or username/group */
  80 static void SidToString(fstring str, DOM_SID *sid, bool _numeric)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82         char **domains = NULL;
  83         char **names = NULL;
  84         enum lsa_SidType *types = NULL;
  85 
  86         sid_to_fstring(str, sid);
  87 
  88         if (_numeric) return;
  89 
  90         /* Ask LSA to convert the sid to a name */
  91 
  92         if (!cli_open_policy_hnd() ||
  93             !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, talloc_tos(),
  94                                                  &pol, 1, sid, &domains, 
  95                                                  &names, &types)) ||
  96             !domains || !domains[0] || !names || !names[0]) {
  97                 return;
  98         }
  99 
 100         /* Converted OK */
 101 
 102         slprintf(str, sizeof(fstring) - 1, "%s%s%s",
 103                  domains[0], lp_winbind_separator(),
 104                  names[0]);
 105         
 106 }
 107 
 108 /* convert a string to a SID, either numeric or username/group */
 109 static bool StringToSid(DOM_SID *sid, const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111         enum lsa_SidType *types = NULL;
 112         DOM_SID *sids = NULL;
 113         bool result = True;
 114 
 115         if (strncmp(str, "S-", 2) == 0) {
 116                 return string_to_sid(sid, str);
 117         }
 118 
 119         if (!cli_open_policy_hnd() ||
 120             !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, talloc_tos(),
 121                                                   &pol, 1, &str, NULL, 1, &sids, 
 122                                                   &types))) {
 123                 result = False;
 124                 goto done;
 125         }
 126 
 127         sid_copy(sid, &sids[0]);
 128  done:
 129 
 130         return result;
 131 }
 132 
 133 #define QUOTA_GET 1
 134 #define QUOTA_SETLIM 2
 135 #define QUOTA_SETFLAGS 3
 136 #define QUOTA_LIST 4
 137 
 138 enum {PARSE_FLAGS,PARSE_LIM};
 139 
 140 static int parse_quota_set(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 141                         char *set_str,
 142                         char **pp_username_str,
 143                         enum SMB_QUOTA_TYPE *qtype,
 144                         int *cmd,
 145                         SMB_NTQUOTA_STRUCT *pqt)
 146 {
 147         char *p = set_str,*p2;
 148         int todo;
 149         bool stop = False;
 150         bool enable = False;
 151         bool deny = False;
 152 
 153         *pp_username_str = NULL;
 154         if (strnequal(set_str,"UQLIM:",6)) {
 155                 p += 6;
 156                 *qtype = SMB_USER_QUOTA_TYPE;
 157                 *cmd = QUOTA_SETLIM;
 158                 todo = PARSE_LIM;
 159                 if ((p2=strstr(p,":"))==NULL) {
 160                         return -1;
 161                 }
 162 
 163                 *p2 = '\0';
 164                 p2++;
 165 
 166                 *pp_username_str = talloc_strdup(ctx, p);
 167                 p = p2;
 168         } else if (strnequal(set_str,"FSQLIM:",7)) {
 169                 p +=7;
 170                 *qtype = SMB_USER_FS_QUOTA_TYPE;
 171                 *cmd = QUOTA_SETLIM;
 172                 todo = PARSE_LIM;
 173         } else if (strnequal(set_str,"FSQFLAGS:",9)) {
 174                 p +=9;
 175                 todo = PARSE_FLAGS;
 176                 *qtype = SMB_USER_FS_QUOTA_TYPE;
 177                 *cmd = QUOTA_SETFLAGS;
 178         } else {
 179                 return -1;
 180         }
 181 
 182         switch (todo) {
 183                 case PARSE_LIM:
 184                         if (sscanf(p,"%"PRIu64"/%"PRIu64,&pqt->softlim,&pqt->hardlim)!=2) {
 185                                 return -1;
 186                         }
 187 
 188                         break;
 189                 case PARSE_FLAGS:
 190                         while (!stop) {
 191 
 192                                 if ((p2=strstr(p,"/"))==NULL) {
 193                                         stop = True;
 194                                 } else {
 195                                         *p2 = '\0';
 196                                         p2++;
 197                                 }
 198 
 199                                 if (strnequal(p,"QUOTA_ENABLED",13)) {
 200                                         enable = True;
 201                                 } else if (strnequal(p,"DENY_DISK",9)) {
 202                                         deny = True;
 203                                 } else if (strnequal(p,"LOG_SOFTLIMIT",13)) {
 204                                         pqt->qflags |= QUOTAS_LOG_THRESHOLD;
 205                                 } else if (strnequal(p,"LOG_HARDLIMIT",13)) {
 206                                         pqt->qflags |= QUOTAS_LOG_LIMIT;
 207                                 } else {
 208                                         return -1;
 209                                 }
 210 
 211                                 p=p2;
 212                         }
 213 
 214                         if (deny) {
 215                                 pqt->qflags |= QUOTAS_DENY_DISK;
 216                         } else if (enable) {
 217                                 pqt->qflags |= QUOTAS_ENABLED;
 218                         }
 219 
 220                         break;
 221         }
 222 
 223         return 0;
 224 }
 225 
 226 static int do_quota(struct cli_state *cli,
     /* [<][>][^][v][top][bottom][index][help] */
 227                 enum SMB_QUOTA_TYPE qtype,
 228                 uint16 cmd,
 229                 const char *username_str,
 230                 SMB_NTQUOTA_STRUCT *pqt)
 231 {
 232         uint32 fs_attrs = 0;
 233         int quota_fnum = 0;
 234         SMB_NTQUOTA_LIST *qtl = NULL;
 235         SMB_NTQUOTA_STRUCT qt;
 236         ZERO_STRUCT(qt);
 237 
 238         if (!cli_get_fs_attr_info(cli, &fs_attrs)) {
 239                 d_printf("Failed to get the filesystem attributes %s.\n",
 240                         cli_errstr(cli));
 241                 return -1;
 242         }
 243 
 244         if (!(fs_attrs & FILE_VOLUME_QUOTAS)) {
 245                 d_printf("Quotas are not supported by the server.\n");
 246                 return 0;
 247         }
 248 
 249         if (!cli_get_quota_handle(cli, &quota_fnum)) {
 250                 d_printf("Quotas are not enabled on this share.\n");
 251                 d_printf("Failed to open %s  %s.\n",
 252                         FAKE_FILE_NAME_QUOTA_WIN32,cli_errstr(cli));
 253                 return -1;
 254         }
 255 
 256         switch(qtype) {
 257                 case SMB_USER_QUOTA_TYPE:
 258                         if (!StringToSid(&qt.sid, username_str)) {
 259                                 d_printf("StringToSid() failed for [%s]\n",username_str);
 260                                 return -1;
 261                         }
 262 
 263                         switch(cmd) {
 264                                 case QUOTA_GET:
 265                                         if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
 266                                                 d_printf("%s cli_get_user_quota %s\n",
 267                                                          cli_errstr(cli),username_str);
 268                                                 return -1;
 269                                         }
 270                                         dump_ntquota(&qt,verbose,numeric,SidToString);
 271                                         break;
 272                                 case QUOTA_SETLIM:
 273                                         pqt->sid = qt.sid;
 274                                         if (!cli_set_user_quota(cli, quota_fnum, pqt)) {
 275                                                 d_printf("%s cli_set_user_quota %s\n",
 276                                                          cli_errstr(cli),username_str);
 277                                                 return -1;
 278                                         }
 279                                         if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
 280                                                 d_printf("%s cli_get_user_quota %s\n",
 281                                                          cli_errstr(cli),username_str);
 282                                                 return -1;
 283                                         }
 284                                         dump_ntquota(&qt,verbose,numeric,SidToString);
 285                                         break;
 286                                 case QUOTA_LIST:
 287                                         if (!cli_list_user_quota(cli, quota_fnum, &qtl)) {
 288                                                 d_printf("%s cli_set_user_quota %s\n",
 289                                                          cli_errstr(cli),username_str);
 290                                                 return -1;
 291                                         }
 292                                         dump_ntquota_list(&qtl,verbose,numeric,SidToString);
 293                                         free_ntquota_list(&qtl);
 294                                         break;
 295                                 default:
 296                                         d_printf("Unknown Error\n");
 297                                         return -1;
 298                         }
 299                         break;
 300                 case SMB_USER_FS_QUOTA_TYPE:
 301                         switch(cmd) {
 302                                 case QUOTA_GET:
 303                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
 304                                                 d_printf("%s cli_get_fs_quota_info\n",
 305                                                          cli_errstr(cli));
 306                                                 return -1;
 307                                         }
 308                                         dump_ntquota(&qt,True,numeric,NULL);
 309                                         break;
 310                                 case QUOTA_SETLIM:
 311                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
 312                                                 d_printf("%s cli_get_fs_quota_info\n",
 313                                                          cli_errstr(cli));
 314                                                 return -1;
 315                                         }
 316                                         qt.softlim = pqt->softlim;
 317                                         qt.hardlim = pqt->hardlim;
 318                                         if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
 319                                                 d_printf("%s cli_set_fs_quota_info\n",
 320                                                          cli_errstr(cli));
 321                                                 return -1;
 322                                         }
 323                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
 324                                                 d_printf("%s cli_get_fs_quota_info\n",
 325                                                          cli_errstr(cli));
 326                                                 return -1;
 327                                         }
 328                                         dump_ntquota(&qt,True,numeric,NULL);
 329                                         break;
 330                                 case QUOTA_SETFLAGS:
 331                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
 332                                                 d_printf("%s cli_get_fs_quota_info\n",
 333                                                          cli_errstr(cli));
 334                                                 return -1;
 335                                         }
 336                                         qt.qflags = pqt->qflags;
 337                                         if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
 338                                                 d_printf("%s cli_set_fs_quota_info\n",
 339                                                          cli_errstr(cli));
 340                                                 return -1;
 341                                         }
 342                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
 343                                                 d_printf("%s cli_get_fs_quota_info\n",
 344                                                          cli_errstr(cli));
 345                                                 return -1;
 346                                         }
 347                                         dump_ntquota(&qt,True,numeric,NULL);
 348                                         break;
 349                                 default:
 350                                         d_printf("Unknown Error\n");
 351                                         return -1;
 352                         }
 353                         break;
 354                 default:
 355                         d_printf("Unknown Error\n");
 356                         return -1;
 357         }
 358 
 359         cli_close(cli, quota_fnum);
 360 
 361         return 0;
 362 }
 363 
 364 /*****************************************************
 365  Return a connection to a server.
 366 *******************************************************/
 367 
 368 static struct cli_state *connect_one(const char *share)
     /* [<][>][^][v][top][bottom][index][help] */
 369 {
 370         struct cli_state *c;
 371         struct sockaddr_storage ss;
 372         NTSTATUS nt_status;
 373         uint32_t flags = 0;
 374 
 375         zero_sockaddr(&ss);
 376 
 377         if (get_cmdline_auth_info_use_machine_account(smbcquotas_auth_info) &&
 378             !set_cmdline_auth_info_machine_account_creds(smbcquotas_auth_info)) {
 379                 return NULL;
 380         }
 381 
 382         if (get_cmdline_auth_info_use_kerberos(smbcquotas_auth_info)) {
 383                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
 384                          CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
 385 
 386         }
 387 
 388         set_cmdline_auth_info_getpass(smbcquotas_auth_info);
 389 
 390         nt_status = cli_full_connection(&c, global_myname(), server, 
 391                                             &ss, 0,
 392                                             share, "?????",
 393                                             get_cmdline_auth_info_username(smbcquotas_auth_info),
 394                                             lp_workgroup(),
 395                                             get_cmdline_auth_info_password(smbcquotas_auth_info),
 396                                             flags,
 397                                             get_cmdline_auth_info_signing_state(smbcquotas_auth_info),
 398                                             NULL);
 399         if (!NT_STATUS_IS_OK(nt_status)) {
 400                 DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
 401                 return NULL;
 402         }
 403 
 404         if (get_cmdline_auth_info_smb_encrypt(smbcquotas_auth_info)) {
 405                 nt_status = cli_cm_force_encryption(c,
 406                                         get_cmdline_auth_info_username(smbcquotas_auth_info),
 407                                         get_cmdline_auth_info_password(smbcquotas_auth_info),
 408                                         lp_workgroup(),
 409                                         share);
 410                 if (!NT_STATUS_IS_OK(nt_status)) {
 411                         cli_shutdown(c);
 412                         return NULL;
 413                 }
 414         }
 415 
 416         return c;
 417 }
 418 
 419 /****************************************************************************
 420   main program
 421 ****************************************************************************/
 422  int main(int argc, const char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 423 {
 424         char *share;
 425         int opt;
 426         int result;
 427         int todo = 0;
 428         char *username_str = NULL;
 429         char *path = NULL;
 430         char *set_str = NULL;
 431         enum SMB_QUOTA_TYPE qtype = SMB_INVALID_QUOTA_TYPE;
 432         int cmd = 0;
 433         static bool test_args = False;
 434         struct cli_state *cli;
 435         bool fix_user = False;
 436         SMB_NTQUOTA_STRUCT qt;
 437         TALLOC_CTX *frame = talloc_stackframe();
 438         poptContext pc;
 439         struct poptOption long_options[] = {
 440                 POPT_AUTOHELP
 441                 { "user", 'u', POPT_ARG_STRING, NULL, 'u', "Show quotas for user", "user" },
 442                 { "list", 'L', POPT_ARG_NONE, NULL, 'L', "List user quotas" },
 443                 { "fs", 'F', POPT_ARG_NONE, NULL, 'F', "Show filesystem quotas" },
 444                 { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls\n\
 445 SETSTRING:\n\
 446 UQLIM:<username>/<softlimit>/<hardlimit> for user quotas\n\
 447 FSQLIM:<softlimit>/<hardlimit> for filesystem defaults\n\
 448 FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
 449                 { "numeric", 'n', POPT_ARG_NONE, NULL, 'n', "Don't resolve sids or limits to names" },
 450                 { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "be verbose" },
 451                 { "test-args", 't', POPT_ARG_NONE, NULL, 'r', "Test arguments"},
 452                 POPT_COMMON_SAMBA
 453                 POPT_COMMON_CREDENTIALS
 454                 { NULL }
 455         };
 456 
 457         load_case_tables();
 458 
 459         ZERO_STRUCT(qt);
 460 
 461         /* set default debug level to 1 regardless of what smb.conf sets */
 462         setup_logging( "smbcquotas", True );
 463         DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
 464         dbf = x_stderr;
 465         x_setbuf( x_stderr, NULL );
 466 
 467         setlinebuf(stdout);
 468 
 469         fault_setup(NULL);
 470 
 471         lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
 472         load_interfaces();
 473 
 474         smbcquotas_auth_info = user_auth_info_init(frame);
 475         if (smbcquotas_auth_info == NULL) {
 476                 exit(1);
 477         }
 478         popt_common_set_auth_info(smbcquotas_auth_info);
 479 
 480         pc = poptGetContext("smbcquotas", argc, argv, long_options, 0);
 481 
 482         poptSetOtherOptionHelp(pc, "//server1/share1");
 483 
 484         while ((opt = poptGetNextOpt(pc)) != -1) {
 485                 switch (opt) {
 486                 case 'n':
 487                         numeric = true;
 488                         break;
 489                 case 'v':
 490                         verbose = true;
 491                         break;
 492                 case 't':
 493                         test_args = true;
 494                         break;
 495                 case 'L':
 496                         if (todo != 0) {
 497                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
 498                                 exit(EXIT_PARSE_ERROR);
 499                         }
 500                         todo = LIST_QUOTA;
 501                         break;
 502 
 503                 case 'F':
 504                         if (todo != 0) {
 505                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
 506                                 exit(EXIT_PARSE_ERROR);
 507                         }
 508                         todo = FS_QUOTA;
 509                         break;
 510 
 511                 case 'u':
 512                         if (todo != 0) {
 513                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
 514                                 exit(EXIT_PARSE_ERROR);
 515                         }
 516                         username_str = talloc_strdup(frame, poptGetOptArg(pc));
 517                         if (!username_str) {
 518                                 exit(EXIT_PARSE_ERROR);
 519                         }
 520                         todo = USER_QUOTA;
 521                         fix_user = True;
 522                         break;
 523 
 524                 case 'S':
 525                         if (todo != 0) {
 526                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
 527                                 exit(EXIT_PARSE_ERROR);
 528                         }
 529                         set_str = talloc_strdup(frame, poptGetOptArg(pc));
 530                         if (!set_str) {
 531                                 exit(EXIT_PARSE_ERROR);
 532                         }
 533                         todo = SET_QUOTA;
 534                         break;
 535                 }
 536         }
 537 
 538         if (todo == 0)
 539                 todo = USER_QUOTA;
 540 
 541         if (!fix_user) {
 542                 username_str = talloc_strdup(
 543                         frame, get_cmdline_auth_info_username(smbcquotas_auth_info));
 544                 if (!username_str) {
 545                         exit(EXIT_PARSE_ERROR);
 546                 }
 547         }
 548 
 549         /* Make connection to server */
 550         if(!poptPeekArg(pc)) {
 551                 poptPrintUsage(pc, stderr, 0);
 552                 exit(EXIT_PARSE_ERROR);
 553         }
 554 
 555         path = talloc_strdup(frame, poptGetArg(pc));
 556         if (!path) {
 557                 printf("Out of memory\n");
 558                 exit(EXIT_PARSE_ERROR);
 559         }
 560 
 561         string_replace(path, '/', '\\');
 562 
 563         server = SMB_STRDUP(path+2);
 564         if (!server) {
 565                 printf("Out of memory\n");
 566                 exit(EXIT_PARSE_ERROR);
 567         }
 568         share = strchr_m(server,'\\');
 569         if (!share) {
 570                 printf("Invalid argument: %s\n", share);
 571                 exit(EXIT_PARSE_ERROR);
 572         }
 573 
 574         *share = 0;
 575         share++;
 576 
 577         if (todo == SET_QUOTA) {
 578                 if (parse_quota_set(talloc_tos(), set_str, &username_str, &qtype, &cmd, &qt)) {
 579                         printf("Invalid argument: -S %s\n", set_str);
 580                         exit(EXIT_PARSE_ERROR);
 581                 }
 582         }
 583 
 584         if (!test_args) {
 585                 cli = connect_one(share);
 586                 if (!cli) {
 587                         exit(EXIT_FAILED);
 588                 }
 589         } else {
 590                 exit(EXIT_OK);
 591         }
 592 
 593 
 594         /* Perform requested action */
 595 
 596         switch (todo) {
 597                 case FS_QUOTA:
 598                         result = do_quota(cli,SMB_USER_FS_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
 599                         break;
 600                 case LIST_QUOTA:
 601                         result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_LIST, username_str, NULL);
 602                         break;
 603                 case USER_QUOTA:
 604                         result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
 605                         break;
 606                 case SET_QUOTA:
 607                         result = do_quota(cli, qtype, cmd, username_str, &qt);
 608                         break;
 609                 default: 
 610                         
 611                         result = EXIT_FAILED;
 612                         break;
 613         }
 614 
 615         talloc_free(frame);
 616 
 617         return result;
 618 }

/* [<][>][^][v][top][bottom][index][help] */