utils/smbcquotas.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    QUOTA 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) Stefan (metze) Metzmacher      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 server;
00028 
00029 /* numeric is set when the user wants numeric SIDs and ACEs rather
00030    than going via LSA calls to resolve them */
00031 static BOOL numeric;
00032 static BOOL verbose;
00033 
00034 enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA};
00035 enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
00036 
00037 static struct cli_state *cli_ipc;
00038 static struct rpc_pipe_client *global_pipe_hnd;
00039 static POLICY_HND pol;
00040 static BOOL got_policy_hnd;
00041 
00042 static struct cli_state *connect_one(const char *share);
00043 
00044 /* Open cli connection and policy handle */
00045 
00046 static BOOL cli_open_policy_hnd(void)
00047 {
00048         /* Initialise cli LSA connection */
00049 
00050         if (!cli_ipc) {
00051                 NTSTATUS ret;
00052                 cli_ipc = connect_one("IPC$");
00053                 global_pipe_hnd = cli_rpc_pipe_open_noauth(cli_ipc, PI_LSARPC, &ret);
00054                 if (!global_pipe_hnd) {
00055                                 return False;
00056                 }
00057         }
00058         
00059         /* Open policy handle */
00060 
00061         if (!got_policy_hnd) {
00062 
00063                 /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
00064                    but NT sends 0x2000000 so we might as well do it too. */
00065 
00066                 if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, cli_ipc->mem_ctx, True, 
00067                                                          GENERIC_EXECUTE_ACCESS, &pol))) {
00068                         return False;
00069                 }
00070 
00071                 got_policy_hnd = True;
00072         }
00073         
00074         return True;
00075 }
00076 
00077 /* convert a SID to a string, either numeric or username/group */
00078 static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric)
00079 {
00080         char **domains = NULL;
00081         char **names = NULL;
00082         enum lsa_SidType *types = NULL;
00083 
00084         sid_to_string(str, sid);
00085 
00086         if (_numeric) return;
00087 
00088         /* Ask LSA to convert the sid to a name */
00089 
00090         if (!cli_open_policy_hnd() ||
00091             !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, cli_ipc->mem_ctx,  
00092                                                  &pol, 1, sid, &domains, 
00093                                                  &names, &types)) ||
00094             !domains || !domains[0] || !names || !names[0]) {
00095                 return;
00096         }
00097 
00098         /* Converted OK */
00099 
00100         slprintf(str, sizeof(fstring) - 1, "%s%s%s",
00101                  domains[0], lp_winbind_separator(),
00102                  names[0]);
00103         
00104 }
00105 
00106 /* convert a string to a SID, either numeric or username/group */
00107 static BOOL StringToSid(DOM_SID *sid, const char *str)
00108 {
00109         enum lsa_SidType *types = NULL;
00110         DOM_SID *sids = NULL;
00111         BOOL result = True;
00112 
00113         if (strncmp(str, "S-", 2) == 0) {
00114                 return string_to_sid(sid, str);
00115         }
00116 
00117         if (!cli_open_policy_hnd() ||
00118             !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, cli_ipc->mem_ctx, 
00119                                                   &pol, 1, &str, NULL, &sids, 
00120                                                   &types))) {
00121                 result = False;
00122                 goto done;
00123         }
00124 
00125         sid_copy(sid, &sids[0]);
00126  done:
00127 
00128         return result;
00129 }
00130 
00131 #define QUOTA_GET 1
00132 #define QUOTA_SETLIM 2
00133 #define QUOTA_SETFLAGS 3
00134 #define QUOTA_LIST 4
00135 
00136 enum {PARSE_FLAGS,PARSE_LIM};
00137 
00138 static int parse_quota_set(pstring set_str, pstring username_str, enum SMB_QUOTA_TYPE *qtype, int *cmd, SMB_NTQUOTA_STRUCT *pqt)
00139 {
00140         char *p = set_str,*p2;
00141         int todo;
00142         BOOL stop = False;
00143         BOOL enable = False;
00144         BOOL deny = False;
00145         
00146         if (strnequal(set_str,"UQLIM:",6)) {
00147                 p += 6;
00148                 *qtype = SMB_USER_QUOTA_TYPE;
00149                 *cmd = QUOTA_SETLIM;
00150                 todo = PARSE_LIM;
00151                 if ((p2=strstr(p,":"))==NULL) {
00152                         return -1;
00153                 }
00154                 
00155                 *p2 = '\0';
00156                 p2++;
00157                 
00158                 fstrcpy(username_str,p);
00159                 p = p2;
00160         } else if (strnequal(set_str,"FSQLIM:",7)) {
00161                 p +=7;
00162                 *qtype = SMB_USER_FS_QUOTA_TYPE;
00163                 *cmd = QUOTA_SETLIM;
00164                 todo = PARSE_LIM;
00165         } else if (strnequal(set_str,"FSQFLAGS:",9)) {
00166                 p +=9;
00167                 todo = PARSE_FLAGS;
00168                 *qtype = SMB_USER_FS_QUOTA_TYPE;
00169                 *cmd = QUOTA_SETFLAGS;
00170         } else {
00171                 return -1;
00172         }
00173 
00174         switch (todo) {
00175                 case PARSE_LIM:
00176 #if defined(HAVE_LONGLONG)
00177                         if (sscanf(p,"%llu/%llu",&pqt->softlim,&pqt->hardlim)!=2) {
00178 #else
00179                         if (sscanf(p,"%lu/%lu",&pqt->softlim,&pqt->hardlim)!=2) {
00180 #endif
00181                                 return -1;
00182                         }
00183                         
00184                         break;
00185                 case PARSE_FLAGS:
00186                         while (!stop) {
00187 
00188                                 if ((p2=strstr(p,"/"))==NULL) {
00189                                         stop = True;
00190                                 } else {
00191                                         *p2 = '\0';
00192                                         p2++;
00193                                 }
00194 
00195                                 if (strnequal(p,"QUOTA_ENABLED",13)) {
00196                                         enable = True;
00197                                 } else if (strnequal(p,"DENY_DISK",9)) {
00198                                         deny = True;
00199                                 } else if (strnequal(p,"LOG_SOFTLIMIT",13)) {
00200                                         pqt->qflags |= QUOTAS_LOG_THRESHOLD;
00201                                 } else if (strnequal(p,"LOG_HARDLIMIT",13)) {
00202                                         pqt->qflags |= QUOTAS_LOG_LIMIT;
00203                                 } else {
00204                                         return -1;
00205                                 }
00206 
00207                                 p=p2;
00208                         }
00209 
00210                         if (deny) {
00211                                 pqt->qflags |= QUOTAS_DENY_DISK;
00212                         } else if (enable) {
00213                                 pqt->qflags |= QUOTAS_ENABLED;
00214                         }
00215                         
00216                         break;  
00217         }
00218 
00219         return 0;
00220 }
00221 
00222 static int do_quota(struct cli_state *cli, enum SMB_QUOTA_TYPE qtype, uint16 cmd, pstring username_str, SMB_NTQUOTA_STRUCT *pqt)
00223 {
00224         uint32 fs_attrs = 0;
00225         int quota_fnum = 0;
00226         SMB_NTQUOTA_LIST *qtl = NULL;
00227         SMB_NTQUOTA_STRUCT qt;
00228         ZERO_STRUCT(qt);
00229 
00230         if (!cli_get_fs_attr_info(cli, &fs_attrs)) {
00231                 d_printf("Failed to get the filesystem attributes %s.\n",
00232                         cli_errstr(cli));
00233                 return -1;
00234         }
00235 
00236         if (!(fs_attrs & FILE_VOLUME_QUOTAS)) {
00237                 d_printf("Quotas are not supported by the server.\n");
00238                 return 0;       
00239         }
00240 
00241         if (!cli_get_quota_handle(cli, &quota_fnum)) {
00242                 d_printf("Quotas are not enabled on this share.\n");
00243                 d_printf("Failed to open %s  %s.\n",
00244                         FAKE_FILE_NAME_QUOTA_WIN32,cli_errstr(cli));
00245                 return -1;
00246         }
00247 
00248         switch(qtype) {
00249                 case SMB_USER_QUOTA_TYPE:
00250                         if (!StringToSid(&qt.sid, username_str)) {
00251                                 d_printf("StringToSid() failed for [%s]\n",username_str);
00252                                 return -1;
00253                         }
00254                         
00255                         switch(cmd) {
00256                                 case QUOTA_GET:
00257                                         if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
00258                                                 d_printf("%s cli_get_user_quota %s\n",
00259                                                          cli_errstr(cli),username_str);
00260                                                 return -1;
00261                                         }
00262                                         dump_ntquota(&qt,verbose,numeric,SidToString);
00263                                         break;
00264                                 case QUOTA_SETLIM:
00265                                         pqt->sid = qt.sid;
00266                                         if (!cli_set_user_quota(cli, quota_fnum, pqt)) {
00267                                                 d_printf("%s cli_set_user_quota %s\n",
00268                                                          cli_errstr(cli),username_str);
00269                                                 return -1;
00270                                         }
00271                                         if (!cli_get_user_quota(cli, quota_fnum, &qt)) {
00272                                                 d_printf("%s cli_get_user_quota %s\n",
00273                                                          cli_errstr(cli),username_str);
00274                                                 return -1;
00275                                         }
00276                                         dump_ntquota(&qt,verbose,numeric,SidToString);
00277                                         break;
00278                                 case QUOTA_LIST:
00279                                         if (!cli_list_user_quota(cli, quota_fnum, &qtl)) {
00280                                                 d_printf("%s cli_set_user_quota %s\n",
00281                                                          cli_errstr(cli),username_str);
00282                                                 return -1;
00283                                         }
00284                                         dump_ntquota_list(&qtl,verbose,numeric,SidToString);
00285                                         free_ntquota_list(&qtl);                                        
00286                                         break;
00287                                 default:
00288                                         d_printf("Unknown Error\n");
00289                                         return -1;
00290                         } 
00291                         break;
00292                 case SMB_USER_FS_QUOTA_TYPE:
00293                         switch(cmd) {
00294                                 case QUOTA_GET:
00295                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
00296                                                 d_printf("%s cli_get_fs_quota_info\n",
00297                                                          cli_errstr(cli));
00298                                                 return -1;
00299                                         }
00300                                         dump_ntquota(&qt,True,numeric,NULL);
00301                                         break;
00302                                 case QUOTA_SETLIM:
00303                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
00304                                                 d_printf("%s cli_get_fs_quota_info\n",
00305                                                          cli_errstr(cli));
00306                                                 return -1;
00307                                         }
00308                                         qt.softlim = pqt->softlim;
00309                                         qt.hardlim = pqt->hardlim;
00310                                         if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
00311                                                 d_printf("%s cli_set_fs_quota_info\n",
00312                                                          cli_errstr(cli));
00313                                                 return -1;
00314                                         }
00315                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
00316                                                 d_printf("%s cli_get_fs_quota_info\n",
00317                                                          cli_errstr(cli));
00318                                                 return -1;
00319                                         }
00320                                         dump_ntquota(&qt,True,numeric,NULL);
00321                                         break;
00322                                 case QUOTA_SETFLAGS:
00323                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
00324                                                 d_printf("%s cli_get_fs_quota_info\n",
00325                                                          cli_errstr(cli));
00326                                                 return -1;
00327                                         }
00328                                         qt.qflags = pqt->qflags;
00329                                         if (!cli_set_fs_quota_info(cli, quota_fnum, &qt)) {
00330                                                 d_printf("%s cli_set_fs_quota_info\n",
00331                                                          cli_errstr(cli));
00332                                                 return -1;
00333                                         }
00334                                         if (!cli_get_fs_quota_info(cli, quota_fnum, &qt)) {
00335                                                 d_printf("%s cli_get_fs_quota_info\n",
00336                                                          cli_errstr(cli));
00337                                                 return -1;
00338                                         }
00339                                         dump_ntquota(&qt,True,numeric,NULL);
00340                                         break;
00341                                 default:
00342                                         d_printf("Unknown Error\n");
00343                                         return -1;
00344                         }               
00345                         break;
00346                 default:
00347                         d_printf("Unknown Error\n");
00348                         return -1;
00349         }
00350 
00351         cli_close(cli, quota_fnum);
00352 
00353         return 0;
00354 }
00355 
00356 /***************************************************** 
00357 return a connection to a server
00358 *******************************************************/
00359 static struct cli_state *connect_one(const char *share)
00360 {
00361         struct cli_state *c;
00362         struct in_addr ip;
00363         NTSTATUS nt_status;
00364         zero_ip(&ip);
00365         
00366         if (!cmdline_auth_info.got_pass) {
00367                 char *pass = getpass("Password: ");
00368                 if (pass) {
00369                         pstrcpy(cmdline_auth_info.password, pass);
00370                         cmdline_auth_info.got_pass = True;
00371                 }
00372         }
00373 
00374         if (NT_STATUS_IS_OK(nt_status = cli_full_connection(&c, global_myname(), server, 
00375                                                             &ip, 0,
00376                                                             share, "?????",  
00377                                                             cmdline_auth_info.username, lp_workgroup(),
00378                                                             cmdline_auth_info.password, 0,
00379                                                             cmdline_auth_info.signing_state, NULL))) {
00380                 return c;
00381         } else {
00382                 DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
00383                 return NULL;
00384         }
00385 }
00386 
00387 /****************************************************************************
00388   main program
00389 ****************************************************************************/
00390  int main(int argc, const char *argv[])
00391 {
00392         char *share;
00393         int opt;
00394         int result;
00395         int todo = 0;
00396         pstring username_str = {0};
00397         pstring path = {0};
00398         pstring set_str = {0};
00399         enum SMB_QUOTA_TYPE qtype = SMB_INVALID_QUOTA_TYPE;
00400         int cmd = 0;
00401         static BOOL test_args = False;
00402         struct cli_state *cli;
00403         BOOL fix_user = False;
00404         SMB_NTQUOTA_STRUCT qt;
00405         poptContext pc;
00406         struct poptOption long_options[] = {
00407                 POPT_AUTOHELP
00408                 { "user", 'u', POPT_ARG_STRING, NULL, 'u', "Show quotas for user", "user" },
00409                 { "list", 'L', POPT_ARG_NONE, NULL, 'L', "List user quotas" },
00410                 { "fs", 'F', POPT_ARG_NONE, NULL, 'F', "Show filesystem quotas" },
00411                 { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls\n\
00412 SETSTRING:\n\
00413 UQLIM:<username>/<softlimit>/<hardlimit> for user quotas\n\
00414 FSQLIM:<softlimit>/<hardlimit> for filesystem defaults\n\
00415 FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
00416                 { "numeric", 'n', POPT_ARG_NONE, &numeric, True, "Don't resolve sids or limits to names" },
00417                 { "verbose", 'v', POPT_ARG_NONE, &verbose, True, "be verbose" },
00418                 { "test-args", 't', POPT_ARG_NONE, &test_args, True, "Test arguments"},
00419                 POPT_COMMON_SAMBA
00420                 POPT_COMMON_CREDENTIALS
00421                 { NULL }
00422         };
00423 
00424         load_case_tables();
00425 
00426         ZERO_STRUCT(qt);
00427 
00428         /* set default debug level to 1 regardless of what smb.conf sets */
00429         setup_logging( "smbcquotas", True );
00430         DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
00431         dbf = x_stderr;
00432         x_setbuf( x_stderr, NULL );
00433 
00434         setlinebuf(stdout);
00435 
00436         fault_setup(NULL);
00437 
00438         lp_load(dyn_CONFIGFILE,True,False,False,True);
00439         load_interfaces();
00440 
00441         pc = poptGetContext("smbcquotas", argc, argv, long_options, 0);
00442         
00443         poptSetOtherOptionHelp(pc, "//server1/share1");
00444 
00445         while ((opt = poptGetNextOpt(pc)) != -1) {
00446                 switch (opt) {
00447                 case 'L':
00448                         if (todo != 0) {
00449                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
00450                                 exit(EXIT_PARSE_ERROR);
00451                         }
00452                         todo = LIST_QUOTA;
00453                         break;
00454 
00455                 case 'F':
00456                         if (todo != 0) {
00457                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
00458                                 exit(EXIT_PARSE_ERROR);
00459                         }
00460                         todo = FS_QUOTA;
00461                         break;
00462                 
00463                 case 'u':
00464                         if (todo != 0) {
00465                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
00466                                 exit(EXIT_PARSE_ERROR);
00467                         }
00468                         pstrcpy(username_str,poptGetOptArg(pc));
00469                         todo = USER_QUOTA;
00470                         fix_user = True;
00471                         break;
00472                 
00473                 case 'S':
00474                         if (todo != 0) {
00475                                 d_printf("Please specify only one option of <-L|-F|-S|-u>\n");
00476                                 exit(EXIT_PARSE_ERROR);
00477                         }
00478                         pstrcpy(set_str,poptGetOptArg(pc));
00479                         todo = SET_QUOTA;
00480                         break;
00481                 }
00482         }
00483 
00484         if (todo == 0)
00485                 todo = USER_QUOTA;
00486 
00487         if (!fix_user)
00488                 pstrcpy(username_str,cmdline_auth_info.username);
00489 
00490         /* Make connection to server */
00491         if(!poptPeekArg(pc)) { 
00492                 poptPrintUsage(pc, stderr, 0);
00493                 exit(EXIT_PARSE_ERROR);
00494         }
00495         
00496         pstrcpy(path, poptGetArg(pc));
00497 
00498         all_string_sub(path,"/","\\",0);
00499 
00500         pstrcpy(server,path+2);
00501         share = strchr_m(server,'\\');
00502         if (!share) {
00503                 share = strchr_m(server,'/');
00504                 if (!share) {
00505                         printf("Invalid argument: %s\n", share);
00506                         exit(EXIT_PARSE_ERROR);
00507                 }
00508         }
00509 
00510         *share = 0;
00511         share++;
00512 
00513         if (todo == SET_QUOTA) {
00514                 if (parse_quota_set(set_str, username_str, &qtype, &cmd, &qt)) {
00515                         printf("Invalid argument: -S %s\n", set_str);
00516                         exit(EXIT_PARSE_ERROR);
00517                 }
00518         }
00519 
00520         if (!test_args) {
00521                 cli = connect_one(share);
00522                 if (!cli) {
00523                         exit(EXIT_FAILED);
00524                 }
00525         } else {
00526                 exit(EXIT_OK);
00527         }
00528 
00529 
00530         /* Perform requested action */
00531 
00532         switch (todo) {
00533                 case FS_QUOTA:
00534                         result = do_quota(cli,SMB_USER_FS_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
00535                         break;
00536                 case LIST_QUOTA:
00537                         result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_LIST, username_str, NULL);
00538                         break;
00539                 case USER_QUOTA:
00540                         result = do_quota(cli,SMB_USER_QUOTA_TYPE, QUOTA_GET, username_str, NULL);
00541                         break;
00542                 case SET_QUOTA:
00543                         result = do_quota(cli, qtype, cmd, username_str, &qt);
00544                         break;
00545                 default: 
00546                         
00547                         result = EXIT_FAILED;
00548                         break;
00549         }
00550 
00551         return result;
00552 }
00553 

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