~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/account_pol.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  account policy storage
 
4
 *  Copyright (C) Jean Fran�ois Micouleau      1998-2001.
 
5
 *  Copyright (C) Andrew Bartlett              2002
 
6
 *  Copyright (C) Guenther Deschner            2004-2005
 
7
 *  
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 3 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *  
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *  GNU General Public License for more details.
 
17
 *  
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include "includes.h"
 
23
static struct db_context *db;
 
24
 
 
25
/* cache all entries for 60 seconds for to save ldap-queries (cache is updated
 
26
 * after this period if admins do not use pdbedit or usermanager but manipulate
 
27
 * ldap directly) - gd */
 
28
 
 
29
#define DATABASE_VERSION        3
 
30
#define AP_TTL                  60
 
31
 
 
32
 
 
33
struct ap_table {
 
34
        int field;
 
35
        const char *string;
 
36
        uint32 default_val;
 
37
        const char *description;
 
38
        const char *ldap_attr;
 
39
};
 
40
 
 
41
static const struct ap_table account_policy_names[] = {
 
42
        {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, 
 
43
                "Minimal password length (default: 5)", 
 
44
                "sambaMinPwdLength" },
 
45
 
 
46
        {AP_PASSWORD_HISTORY, "password history", 0,
 
47
                "Length of Password History Entries (default: 0 => off)", 
 
48
                "sambaPwdHistoryLength" },
 
49
                
 
50
        {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0,
 
51
                "Force Users to logon for password change (default: 0 => off, 2 => on)",
 
52
                "sambaLogonToChgPwd" },
 
53
        
 
54
        {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1,
 
55
                "Maximum password age, in seconds (default: -1 => never expire passwords)", 
 
56
                "sambaMaxPwdAge" },
 
57
                
 
58
        {AP_MIN_PASSWORD_AGE,"minimum password age", 0,
 
59
                "Minimal password age, in seconds (default: 0 => allow immediate password change)", 
 
60
                "sambaMinPwdAge" },
 
61
                
 
62
        {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30,
 
63
                "Lockout duration in minutes (default: 30, -1 => forever)",
 
64
                "sambaLockoutDuration" },
 
65
                
 
66
        {AP_RESET_COUNT_TIME, "reset count minutes", 30,
 
67
                "Reset time after lockout in minutes (default: 30)", 
 
68
                "sambaLockoutObservationWindow" },
 
69
                
 
70
        {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0,
 
71
                "Lockout users after bad logon attempts (default: 0 => off)", 
 
72
                "sambaLockoutThreshold" },
 
73
                
 
74
        {AP_TIME_TO_LOGOUT, "disconnect time", (uint32) -1,
 
75
                "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", 
 
76
                "sambaForceLogoff" }, 
 
77
                
 
78
        {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0,
 
79
                "Allow Machine Password changes (default: 0 => off)",
 
80
                "sambaRefuseMachinePwdChange" },
 
81
                
 
82
        {0, NULL, 0, "", NULL}
 
83
};
 
84
 
 
85
void account_policy_names_list(const char ***names, int *num_names)
 
86
{       
 
87
        const char **nl;
 
88
        int i, count;
 
89
 
 
90
        for (count=0; account_policy_names[count].string; count++) {
 
91
        }
 
92
        nl = SMB_MALLOC_ARRAY(const char *, count);
 
93
        if (!nl) {
 
94
                *num_names = 0;
 
95
                return;
 
96
        }
 
97
        for (i=0; account_policy_names[i].string; i++) {
 
98
                nl[i] = account_policy_names[i].string;
 
99
        }
 
100
        *num_names = count;
 
101
        *names = nl;
 
102
        return;
 
103
}
 
104
 
 
105
/****************************************************************************
 
106
Get the account policy name as a string from its #define'ed number
 
107
****************************************************************************/
 
108
 
 
109
const char *decode_account_policy_name(int field)
 
110
{
 
111
        int i;
 
112
        for (i=0; account_policy_names[i].string; i++) {
 
113
                if (field == account_policy_names[i].field) {
 
114
                        return account_policy_names[i].string;
 
115
                }
 
116
        }
 
117
        return NULL;
 
118
}
 
119
 
 
120
/****************************************************************************
 
121
Get the account policy LDAP attribute as a string from its #define'ed number
 
122
****************************************************************************/
 
123
 
 
124
const char *get_account_policy_attr(int field)
 
125
{
 
126
        int i;
 
127
        for (i=0; account_policy_names[i].field; i++) {
 
128
                if (field == account_policy_names[i].field) {
 
129
                        return account_policy_names[i].ldap_attr;
 
130
                }
 
131
        }
 
132
        return NULL;
 
133
}
 
134
 
 
135
/****************************************************************************
 
136
Get the account policy description as a string from its #define'ed number
 
137
****************************************************************************/
 
138
 
 
139
const char *account_policy_get_desc(int field)
 
140
{
 
141
        int i;
 
142
        for (i=0; account_policy_names[i].string; i++) {
 
143
                if (field == account_policy_names[i].field) {
 
144
                        return account_policy_names[i].description;
 
145
                }
 
146
        }
 
147
        return NULL;
 
148
}
 
149
 
 
150
/****************************************************************************
 
151
Get the account policy name as a string from its #define'ed number
 
152
****************************************************************************/
 
153
 
 
154
int account_policy_name_to_fieldnum(const char *name)
 
155
{
 
156
        int i;
 
157
        for (i=0; account_policy_names[i].string; i++) {
 
158
                if (strcmp(name, account_policy_names[i].string) == 0) {
 
159
                        return account_policy_names[i].field;
 
160
                }
 
161
        }
 
162
        return 0;
 
163
}
 
164
 
 
165
/*****************************************************************************
 
166
Get default value for account policy
 
167
*****************************************************************************/
 
168
 
 
169
bool account_policy_get_default(int account_policy, uint32 *val)
 
170
{
 
171
        int i;
 
172
        for (i=0; account_policy_names[i].field; i++) {
 
173
                if (account_policy_names[i].field == account_policy) {
 
174
                        *val = account_policy_names[i].default_val;
 
175
                        return True;
 
176
                }
 
177
        }
 
178
        DEBUG(0,("no default for account_policy index %d found. This should never happen\n", 
 
179
                account_policy));
 
180
        return False;
 
181
}
 
182
 
 
183
/*****************************************************************************
 
184
 Set default for a field if it is empty
 
185
*****************************************************************************/
 
186
 
 
187
static bool account_policy_set_default_on_empty(int account_policy)
 
188
{
 
189
 
 
190
        uint32 value;
 
191
 
 
192
        if (!account_policy_get(account_policy, &value) && 
 
193
            !account_policy_get_default(account_policy, &value)) {
 
194
                return False;
 
195
        }
 
196
 
 
197
        return account_policy_set(account_policy, value);
 
198
}
 
199
 
 
200
/*****************************************************************************
 
201
 Open the account policy tdb.
 
202
***`*************************************************************************/
 
203
 
 
204
bool init_account_policy(void)
 
205
{
 
206
 
 
207
        const char *vstring = "INFO/version";
 
208
        uint32 version;
 
209
        int i;
 
210
 
 
211
        if (db != NULL) {
 
212
                return True;
 
213
        }
 
214
 
 
215
        db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT,
 
216
                     O_RDWR, 0600);
 
217
 
 
218
        if (db == NULL) { /* the account policies files does not exist or open
 
219
                           * failed, try to create a new one */
 
220
                db = db_open(NULL, state_path("account_policy.tdb"), 0,
 
221
                             TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
 
222
                if (db == NULL) {
 
223
                        DEBUG(0,("Failed to open account policy database\n"));
 
224
                        return False;
 
225
                }
 
226
        }
 
227
 
 
228
        version = dbwrap_fetch_int32(db, vstring);
 
229
        if (version == DATABASE_VERSION) {
 
230
                return true;
 
231
        }
 
232
 
 
233
        /* handle a Samba upgrade */
 
234
 
 
235
        if (db->transaction_start(db) != 0) {
 
236
                DEBUG(0, ("transaction_start failed\n"));
 
237
                TALLOC_FREE(db);
 
238
                return false;
 
239
        }
 
240
 
 
241
        version = dbwrap_fetch_int32(db, vstring);
 
242
        if (version == DATABASE_VERSION) {
 
243
                /*
 
244
                 * Race condition
 
245
                 */
 
246
                if (db->transaction_cancel(db)) {
 
247
                        smb_panic("transaction_cancel failed");
 
248
                }
 
249
                return true;
 
250
        }
 
251
 
 
252
        if (version != DATABASE_VERSION) {
 
253
                if (dbwrap_store_uint32(db, vstring, DATABASE_VERSION) != 0) {
 
254
                        DEBUG(0, ("dbwrap_store_uint32 failed\n"));
 
255
                        goto cancel;
 
256
                }
 
257
 
 
258
                for (i=0; account_policy_names[i].field; i++) {
 
259
 
 
260
                        if (!account_policy_set_default_on_empty(account_policy_names[i].field)) {
 
261
                                DEBUG(0,("failed to set default value in account policy tdb\n"));
 
262
                                goto cancel;
 
263
                        }
 
264
                }
 
265
        }
 
266
 
 
267
        /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
 
268
 
 
269
        privilege_create_account( &global_sid_World );
 
270
        privilege_create_account( &global_sid_Builtin_Account_Operators );
 
271
        privilege_create_account( &global_sid_Builtin_Server_Operators );
 
272
        privilege_create_account( &global_sid_Builtin_Print_Operators );
 
273
        privilege_create_account( &global_sid_Builtin_Backup_Operators );
 
274
 
 
275
        /* BUILTIN\Administrators get everything -- *always* */
 
276
 
 
277
        if ( lp_enable_privileges() ) {
 
278
                if ( !grant_all_privileges( &global_sid_Builtin_Administrators ) ) {
 
279
                        DEBUG(1,("init_account_policy: Failed to grant privileges "
 
280
                                "to BUILTIN\\Administrators!\n"));
 
281
                }
 
282
        }
 
283
 
 
284
        if (db->transaction_commit(db) != 0) {
 
285
                DEBUG(0, ("transaction_commit failed\n"));
 
286
                TALLOC_FREE(db);
 
287
                return false;
 
288
        }
 
289
 
 
290
        return True;
 
291
 
 
292
 cancel:
 
293
        if (db->transaction_cancel(db)) {
 
294
                smb_panic("transaction_cancel failed");
 
295
        }
 
296
        TALLOC_FREE(db);
 
297
 
 
298
        return false;
 
299
}
 
300
 
 
301
/*****************************************************************************
 
302
Get an account policy (from tdb) 
 
303
*****************************************************************************/
 
304
 
 
305
bool account_policy_get(int field, uint32 *value)
 
306
{
 
307
        const char *name;
 
308
        uint32 regval;
 
309
 
 
310
        if (!init_account_policy()) {
 
311
                return False;
 
312
        }
 
313
 
 
314
        if (value) {
 
315
                *value = 0;
 
316
        }
 
317
 
 
318
        name = decode_account_policy_name(field);
 
319
        if (name == NULL) {
 
320
                DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type!  Cannot get, returning 0.\n", field));
 
321
                return False;
 
322
        }
 
323
        
 
324
        if (!dbwrap_fetch_uint32(db, name, &regval)) {
 
325
                DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, name));
 
326
                return False;
 
327
        }
 
328
        
 
329
        if (value) {
 
330
                *value = regval;
 
331
        }
 
332
 
 
333
        DEBUG(10,("account_policy_get: name: %s, val: %d\n", name, regval));
 
334
        return True;
 
335
}
 
336
 
 
337
 
 
338
/****************************************************************************
 
339
Set an account policy (in tdb) 
 
340
****************************************************************************/
 
341
 
 
342
bool account_policy_set(int field, uint32 value)
 
343
{
 
344
        const char *name;
 
345
        NTSTATUS status;
 
346
 
 
347
        if (!init_account_policy()) {
 
348
                return False;
 
349
        }
 
350
 
 
351
        name = decode_account_policy_name(field);
 
352
        if (name == NULL) {
 
353
                DEBUG(1, ("Field %d is not a valid account policy type!  Cannot set.\n", field));
 
354
                return False;
 
355
        }
 
356
 
 
357
        status = dbwrap_trans_store_uint32(db, name, value);
 
358
        if (!NT_STATUS_IS_OK(status)) {
 
359
                DEBUG(1, ("store_uint32 failed for field %d (%s) on value "
 
360
                          "%u: %s\n", field, name, value, nt_errstr(status)));
 
361
                return False;
 
362
        }
 
363
 
 
364
        DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value));
 
365
        
 
366
        return True;
 
367
}
 
368
 
 
369
/****************************************************************************
 
370
Set an account policy in the cache 
 
371
****************************************************************************/
 
372
 
 
373
bool cache_account_policy_set(int field, uint32 value)
 
374
{
 
375
        const char *policy_name = NULL;
 
376
        char *cache_key = NULL;
 
377
        char *cache_value = NULL;
 
378
        bool ret = False;
 
379
 
 
380
        policy_name = decode_account_policy_name(field);
 
381
        if (policy_name == NULL) {
 
382
                DEBUG(0,("cache_account_policy_set: no policy found\n"));
 
383
                return False;
 
384
        }
 
385
 
 
386
        if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
 
387
                DEBUG(0, ("asprintf failed\n"));
 
388
                goto done;
 
389
        }
 
390
 
 
391
        if (asprintf(&cache_value, "%lu\n", (unsigned long)value) < 0) {
 
392
                DEBUG(0, ("asprintf failed\n"));
 
393
                goto done;
 
394
        }
 
395
 
 
396
        DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
 
397
 
 
398
        ret = gencache_set(cache_key, cache_value, time(NULL)+AP_TTL);
 
399
 
 
400
 done:
 
401
        SAFE_FREE(cache_key);
 
402
        SAFE_FREE(cache_value);
 
403
        return ret;
 
404
}
 
405
 
 
406
/*****************************************************************************
 
407
Get an account policy from the cache 
 
408
*****************************************************************************/
 
409
 
 
410
bool cache_account_policy_get(int field, uint32 *value)
 
411
{
 
412
        const char *policy_name = NULL;
 
413
        char *cache_key = NULL;
 
414
        char *cache_value = NULL;
 
415
        bool ret = False;
 
416
 
 
417
        policy_name = decode_account_policy_name(field);
 
418
        if (policy_name == NULL) {
 
419
                DEBUG(0,("cache_account_policy_set: no policy found\n"));
 
420
                return False;
 
421
        }
 
422
 
 
423
        if (asprintf(&cache_key, "ACCT_POL/%s", policy_name) < 0) {
 
424
                DEBUG(0, ("asprintf failed\n"));
 
425
                goto done;
 
426
        }
 
427
 
 
428
        if (gencache_get(cache_key, &cache_value, NULL)) {
 
429
                uint32 tmp = strtoul(cache_value, NULL, 10);
 
430
                *value = tmp;
 
431
                ret = True;
 
432
        }
 
433
 
 
434
 done:
 
435
        SAFE_FREE(cache_key);
 
436
        SAFE_FREE(cache_value);
 
437
        return ret;
 
438
}
 
439
 
 
440
/****************************************************************************
 
441
****************************************************************************/
 
442
 
 
443
struct db_context *get_account_pol_db( void )
 
444
{
 
445
 
 
446
        if ( db == NULL ) {
 
447
                if ( !init_account_policy() ) {
 
448
                        return NULL;
 
449
                }
 
450
        }
 
451
 
 
452
        return db;
 
453
}
 
454