00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <linux/types.h>
00010 #include <linux/sched.h>
00011 #include <linux/mm.h>
00012 #include <linux/init.h>
00013 #include <linux/random.h>
00014 #include <asm/uaccess.h>
00015 #include <rsbac/types.h>
00016 #include <rsbac/aci_data_structures.h>
00017 #include <rsbac/um_types.h>
00018 #include <rsbac/error.h>
00019 #include <rsbac/helpers.h>
00020 #include <rsbac/adf.h>
00021 #include <rsbac/aci.h>
00022 #include <rsbac/um.h>
00023 #include <rsbac/lists.h>
00024 #include <rsbac/proc_fs.h>
00025 #include <rsbac/rkmem.h>
00026 #include <rsbac/getname.h>
00027 #include <linux/string.h>
00028 #include <linux/smp_lock.h>
00029 #include <linux/delay.h>
00030 #ifdef CONFIG_RSBAC_UM_DIGEST
00031 #include <linux/crypto.h>
00032 #include <asm/scatterlist.h>
00033 #endif
00034
00035
00036
00037
00038 static rsbac_list_handle_t user_handle;
00039 static rsbac_list_handle_t group_handle;
00040 #ifdef CONFIG_RSBAC_UM_PWHISTORY
00041 static rsbac_list_handle_t user_pwhistory_handle;
00042 #endif
00043 #define EXTRA_ROOM 20
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 static u_int nr_user_hashes = RSBAC_UM_NR_USER_LISTS;
00058 static u_int nr_group_hashes = RSBAC_UM_NR_GROUP_LISTS;
00059
00060 #ifdef CONFIG_RSBAC_UM_PWHISTORY
00061 static u_int nr_user_pwhistory_hashes = RSBAC_UM_NR_USER_PWHISTORY_LISTS;
00062 #endif
00063
00064
00065 #if defined(CONFIG_RSBAC_PROC)
00066 #if 0
00067 static int
00068 um_users_proc_info(char *buffer, char **start, off_t offset, int length)
00069 {
00070 int len = 0;
00071 off_t pos = 0;
00072 off_t begin = 0;
00073 struct rsbac_mac_device_list_item_t *device_p;
00074 u_long dflags;
00075
00076 if (!rsbac_is_initialized())
00077 return (-ENOSYS);
00078
00079 len +=
00080 sprintf(buffer, "%u RSBAC MAC Devices\n-------------------\n",
00081 device_list_head.count);
00082
00083
00084 rsbac_read_lock(&device_list_head.lock, &dflags);
00085
00086 for (device_p = device_list_head.head; device_p;
00087 device_p = device_p->next) {
00088 len +=
00089 sprintf(buffer + len,
00090 "%02u:%02u with mount_count = %u\n",
00091 RSBAC_MAJOR(device_p->id),
00092 RSBAC_MINOR(device_p->id),
00093 device_p->mount_count);
00094 pos = begin + len;
00095 if (pos < offset) {
00096 len = 0;
00097 begin = pos;
00098 }
00099 if (pos > offset + length)
00100 break;
00101 }
00102
00103
00104 rsbac_read_unlock(&device_list_head.lock, &dflags);
00105
00106 *start = buffer + (offset - begin);
00107 len -= (offset - begin);
00108
00109 if (len > length)
00110 len = length;
00111 return len;
00112 }
00113 #endif
00114
00115 static int
00116 stats_um_proc_info(char *buffer, char **start, off_t offset, int length)
00117 {
00118 u_int len = 0;
00119 off_t pos = 0;
00120 off_t begin = 0;
00121
00122 u_long user_count;
00123 u_long group_count;
00124 u_long member_count;
00125
00126 union rsbac_target_id_t rsbac_target_id;
00127 union rsbac_attribute_value_t rsbac_attribute_value;
00128
00129 if (!rsbac_is_initialized()) {
00130 rsbac_printk(KERN_WARNING "stats_um_proc_info(): RSBAC not initialized\n");
00131 return (-RSBAC_ENOTINITIALIZED);
00132 }
00133 rsbac_pr_debug(aef_um, "calling ADF\n");
00134 rsbac_target_id.scd = ST_rsbac;
00135 rsbac_attribute_value.dummy = 0;
00136 if (!rsbac_adf_request(R_GET_STATUS_DATA,
00137 current->pid,
00138 T_SCD,
00139 rsbac_target_id,
00140 A_none, rsbac_attribute_value)) {
00141 return -EPERM;
00142 }
00143
00144 user_count = rsbac_list_lol_count(user_handle);
00145 member_count = rsbac_list_lol_all_subcount(user_handle);
00146 group_count = rsbac_list_count(group_handle);
00147
00148 len += sprintf(buffer, "UM Status\n---------\n");
00149
00150 len +=
00151 sprintf(buffer + len,
00152 "%lu user items with sum of %lu group memberships, %lu group items\n",
00153 user_count, member_count, group_count);
00154 pos = begin + len;
00155 if (pos < offset) {
00156 len = 0;
00157 begin = pos;
00158 }
00159 *start = buffer + (offset - begin);
00160 len -= (offset - begin);
00161
00162 if (len > length)
00163 len = length;
00164 return len;
00165 }
00166
00167 #endif
00168
00169 static int name_compare(void *data1, void *data2)
00170 {
00171 struct rsbac_um_user_entry_t *entry_p = data1;
00172 char *name = data2;
00173
00174 if (!entry_p || !name)
00175 return 1;
00176
00177 return strcmp(entry_p->name, name);
00178 }
00179
00180 static int group_name_compare(void *data1, void *data2)
00181 {
00182 struct rsbac_um_group_entry_t *entry_p = data1;
00183 char *name = data2;
00184
00185 if (!entry_p || !name)
00186 return 1;
00187
00188 return strcmp(entry_p->name, name);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 #ifdef CONFIG_RSBAC_INIT_DELAY
00207 int rsbac_init_um(void)
00208 #else
00209 int __init rsbac_init_um(void)
00210 #endif
00211 {
00212 int err = 0;
00213 struct proc_dir_entry *tmp_entry_p;
00214 struct rsbac_list_info_t *list_info_p;
00215 struct rsbac_list_lol_info_t *lol_info_p;
00216
00217 if (rsbac_is_initialized()) {
00218 rsbac_printk(KERN_WARNING "rsbac_init_um(): RSBAC already initialized\n");
00219 return (-RSBAC_EREINIT);
00220 }
00221
00222
00223 rsbac_printk(KERN_INFO "rsbac_init_um(): Initializing RSBAC: User Management subsystem\n");
00224
00225 list_info_p = kmalloc(sizeof(*list_info_p), GFP_KERNEL);
00226 if (!list_info_p) {
00227 return -ENOMEM;
00228 }
00229 lol_info_p = kmalloc(sizeof(*lol_info_p), GFP_KERNEL);
00230 if (!lol_info_p) {
00231 kfree(list_info_p);
00232 return -ENOMEM;
00233 }
00234
00235 lol_info_p->version = RSBAC_UM_USER_LIST_VERSION;
00236 lol_info_p->key = RSBAC_UM_USER_LIST_KEY;
00237 lol_info_p->desc_size = sizeof(rsbac_uid_t);
00238 lol_info_p->data_size = sizeof(struct rsbac_um_user_entry_t);
00239 lol_info_p->subdesc_size = sizeof(rsbac_gid_t);
00240 lol_info_p->subdata_size = 0;
00241 lol_info_p->max_age = 0;
00242 nr_user_hashes = RSBAC_UM_NR_USER_LISTS;
00243 err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
00244 &user_handle, lol_info_p,
00245 #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
00246 RSBAC_LIST_BACKUP |
00247 #endif
00248 RSBAC_LIST_PERSIST |
00249 RSBAC_LIST_REPLICATE |
00250 RSBAC_LIST_AUTO_HASH_RESIZE, NULL,
00251 NULL, NULL, NULL, NULL, NULL,
00252 RSBAC_UM_USER_LIST_NAME,
00253 RSBAC_AUTO_DEV,
00254 nr_user_hashes,
00255 rsbac_list_hash_uid,
00256 RSBAC_UM_OLD_USER_LIST_NAME);
00257 if (err) {
00258 char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00259
00260 if (tmp) {
00261 rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user list of lists %s failed with error %s\n",
00262 RSBAC_UM_USER_LIST_NAME, get_error_name(tmp, err));
00263 }
00264 }
00265
00266 list_info_p->version = RSBAC_UM_GROUP_LIST_VERSION;
00267 list_info_p->key = RSBAC_UM_GROUP_LIST_KEY;
00268 list_info_p->desc_size = sizeof(rsbac_gid_t);
00269 list_info_p->data_size = sizeof(struct rsbac_um_group_entry_t);
00270 list_info_p->max_age = 0;
00271 nr_group_hashes = RSBAC_UM_NR_GROUP_LISTS;
00272 err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
00273 &group_handle, list_info_p,
00274 #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
00275 RSBAC_LIST_BACKUP |
00276 #endif
00277 RSBAC_LIST_PERSIST |
00278 RSBAC_LIST_REPLICATE |
00279 RSBAC_LIST_AUTO_HASH_RESIZE, NULL, NULL,
00280 NULL, RSBAC_UM_GROUP_LIST_NAME,
00281 RSBAC_AUTO_DEV,
00282 nr_group_hashes,
00283 rsbac_list_hash_gid,
00284 RSBAC_UM_OLD_GROUP_LIST_NAME);
00285 if (err) {
00286 char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00287
00288 if (tmp) {
00289 rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering group list %s failed with error %s\n",
00290 RSBAC_UM_GROUP_LIST_NAME, get_error_name(tmp, err));
00291 }
00292 }
00293
00294 #ifdef CONFIG_RSBAC_UM_PWHISTORY
00295 {
00296 __u8 def_max_history = CONFIG_RSBAC_UM_PWHISTORY_MAX;
00297
00298 lol_info_p->version = RSBAC_UM_USER_PWHISTORY_LIST_VERSION;
00299 lol_info_p->key = RSBAC_UM_USER_PWHISTORY_LIST_KEY;
00300 lol_info_p->desc_size = sizeof(rsbac_uid_t);
00301 lol_info_p->data_size = sizeof(__u8);
00302 lol_info_p->subdesc_size = sizeof(__u32);
00303 lol_info_p->subdata_size = RSBAC_UM_PASS_LEN;
00304 lol_info_p->max_age = 0;
00305 nr_user_pwhistory_hashes = RSBAC_UM_NR_USER_LISTS;
00306 err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
00307 &user_pwhistory_handle,
00308 lol_info_p,
00309 #ifdef CONFIG_RSBAC_DEV_USER_BACKUP
00310 RSBAC_LIST_BACKUP |
00311 #endif
00312 RSBAC_LIST_PERSIST |
00313 RSBAC_LIST_DEF_DATA |
00314 RSBAC_LIST_AUTO_HASH_RESIZE,
00315 NULL, NULL, NULL, NULL,
00316 &def_max_history, NULL,
00317 RSBAC_UM_USER_PWHISTORY_LIST_NAME,
00318 RSBAC_AUTO_DEV,
00319 nr_user_pwhistory_hashes,
00320 rsbac_list_hash_uid,
00321 RSBAC_UM_OLD_USER_PWHISTORY_LIST_NAME);
00322 if (err) {
00323 char *tmp =
00324 rsbac_kmalloc(RSBAC_MAXNAMELEN);
00325
00326 if (tmp) {
00327 rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user password history list of lists %s failed with error %s\n",
00328 RSBAC_UM_USER_PWHISTORY_LIST_NAME,
00329 get_error_name(tmp,
00330 err));
00331 }
00332 }
00333 }
00334 #endif
00335
00336
00337 #if defined(CONFIG_RSBAC_PROC)
00338 tmp_entry_p = create_proc_entry("stats_um",
00339 S_IFREG | S_IRUGO,
00340 proc_rsbac_root_p);
00341 if (tmp_entry_p) {
00342 tmp_entry_p->get_info = stats_um_proc_info;
00343 }
00344 #endif
00345
00346 rsbac_pr_debug(ds_um, "Ready.\n");
00347 kfree(list_info_p);
00348 kfree(lol_info_p);
00349 return (err);
00350 }
00351
00352
00353
00354
00355 int rsbac_stats_um(void)
00356 {
00357 u_long user_count;
00358 u_long group_count;
00359 u_long member_count;
00360
00361 union rsbac_target_id_t rsbac_target_id;
00362 union rsbac_attribute_value_t rsbac_attribute_value;
00363
00364 if (!rsbac_is_initialized()) {
00365 rsbac_printk(KERN_WARNING "rsbac_stats_um(): RSBAC not initialized\n");
00366 return (-RSBAC_ENOTINITIALIZED);
00367 }
00368 rsbac_pr_debug(aef_um, "calling ADF\n");
00369 rsbac_target_id.scd = ST_rsbac;
00370 rsbac_attribute_value.dummy = 0;
00371 if (!rsbac_adf_request(R_GET_STATUS_DATA,
00372 current->pid,
00373 T_SCD,
00374 rsbac_target_id,
00375 A_none, rsbac_attribute_value)) {
00376 return -EPERM;
00377 }
00378
00379 user_count = rsbac_list_lol_count(user_handle);
00380 member_count = rsbac_list_lol_all_subcount(user_handle);
00381 group_count = rsbac_list_count(group_handle);
00382 rsbac_printk(KERN_INFO "UM Status\n---------\n");
00383
00384 rsbac_printk(KERN_INFO "%lu user items with sum of %lu group memberships, %lu group items\n",
00385 user_count, member_count, group_count);
00386 return 0;
00387 }
00388
00389
00390
00391
00392
00393
00394 #ifndef offset_in_page
00395 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
00396 #endif
00397
00398 static inline void new_salt(__u32 * salt_p)
00399 {
00400 *salt_p = 0;
00401 while (!*salt_p)
00402 get_random_bytes(salt_p, sizeof(*salt_p));
00403 }
00404
00405 int rsbac_um_hash(char *pass, __u32 salt)
00406 {
00407 #ifdef CONFIG_RSBAC_UM_DIGEST
00408 char *buffer;
00409 struct scatterlist sg[1];
00410 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
00411 struct crypto_hash *tfm;
00412 struct hash_desc hd;
00413 #else
00414 struct crypto_tfm *tfm;
00415 #endif
00416 u_int len;
00417 u_int plen;
00418
00419 plen = strlen(pass);
00420 len = rsbac_max(plen + sizeof(salt), RSBAC_UM_PASS_LEN);
00421 buffer = rsbac_kmalloc(len);
00422 if (!buffer)
00423 return -RSBAC_ENOMEM;
00424
00425 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
00426 if (!crypto_has_hash("sha1", 0, 0)) {
00427 rsbac_printk(KERN_WARNING "rsbac_um_hash(): User management configured for crypto API with SHA1, but SHA1 is not available!\n");
00428 rsbac_kfree(buffer);
00429 return -RSBAC_ENOTFOUND;
00430 }
00431 #else
00432 if (!crypto_alg_available("sha1", 0)) {
00433 rsbac_printk(KERN_WARNING "rsbac_um_hash(): User management configured for crypto API with SHA1, but SHA1 is not available!\n");
00434 rsbac_kfree(buffer);
00435 return -RSBAC_ENOTFOUND;
00436 }
00437 #endif
00438
00439 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
00440 tfm = crypto_alloc_hash("sha1", 0, 0);
00441 #else
00442 tfm = crypto_alloc_tfm("sha1", 0);
00443 #endif
00444 if (!tfm) {
00445 rsbac_printk(KERN_WARNING "pid %u/%.15s: rsbac_um_hash(): Could not allocate tfm for SHA1!\n",
00446 current->pid, current->comm);
00447 rsbac_kfree(buffer);
00448 return -RSBAC_ENOMEM;
00449 }
00450 memset(buffer, 0, len);
00451 memcpy(buffer, &salt, sizeof(salt));
00452 strcpy(buffer + sizeof(salt), pass);
00453 sg[0].page = virt_to_page(buffer);
00454 sg[0].offset = offset_in_page(buffer);
00455 sg[0].length = plen + sizeof(salt);
00456
00457 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
00458 hd.tfm = tfm;
00459 hd.flags = 0;
00460 crypto_hash_init(&hd);
00461 crypto_hash_update(&hd, sg, 1);
00462 crypto_hash_final(&hd, buffer);
00463 crypto_free_hash(tfm);
00464 #else
00465 crypto_digest_init(tfm);
00466 crypto_digest_update(tfm, sg, 1);
00467 crypto_digest_final(tfm, buffer);
00468 crypto_free_tfm(tfm);
00469 #endif
00470
00471 memcpy(pass, buffer, RSBAC_UM_PASS_LEN);
00472 rsbac_kfree(buffer);
00473 return 0;
00474 #else
00475
00476 u_int len;
00477
00478 len = strlen(pass);
00479 if (len < RSBAC_UM_PASS_LEN)
00480 memset(pass + len, 0, RSBAC_UM_PASS_LEN - len);
00481 return 0;
00482 #endif
00483 }
00484
00485 int rsbac_um_get_uid(rsbac_list_ta_number_t ta_number,
00486 char *name, rsbac_uid_t * uid_p)
00487 {
00488 if (!name || !uid_p)
00489 return -RSBAC_EINVALIDPOINTER;
00490 if (!rsbac_ta_list_lol_get_desc(ta_number,
00491 user_handle,
00492 uid_p, name, name_compare))
00493 return 0;
00494 else
00495 return -RSBAC_ENOTFOUND;
00496 }
00497
00498 int rsbac_um_get_gid(rsbac_list_ta_number_t ta_number,
00499 char *name, rsbac_gid_t * gid_p)
00500 {
00501 if (!name || !gid_p)
00502 return -RSBAC_EINVALIDPOINTER;
00503 if (!rsbac_ta_list_get_desc(ta_number,
00504 group_handle,
00505 gid_p,
00506 name, group_name_compare))
00507 return 0;
00508 else
00509 return -RSBAC_ENOTFOUND;
00510 }
00511
00512 int rsbac_um_add_user(rsbac_list_ta_number_t ta_number,
00513 rsbac_uid_t * user_p,
00514 struct rsbac_um_user_entry_t *entry_p,
00515 char *pass, rsbac_time_t ttl)
00516 {
00517 int err;
00518 rsbac_uid_t user;
00519
00520 if (!rsbac_is_initialized()) {
00521 rsbac_printk(KERN_WARNING "rsbac_um_add_user(): RSBAC not initialized\n");
00522 return (-RSBAC_ENOTINITIALIZED);
00523 }
00524 if (!entry_p)
00525 return -RSBAC_EINVALIDPOINTER;
00526 user = *user_p;
00527 if (!rsbac_um_get_uid(ta_number, entry_p->name, &user))
00528 return -RSBAC_EEXISTS;
00529 #ifdef CONFIG_RSBAC_UM_EXCL
00530 if (!rsbac_um_no_excl
00531 && !rsbac_ta_list_exist(ta_number,
00532 group_handle,
00533 &entry_p->group)) {
00534 rsbac_printk(KERN_INFO "rsbac_um_add_user(): gid %u not known to RSBAC User Management!\n",
00535 entry_p->group);
00536 return -RSBAC_EINVALIDVALUE;
00537 }
00538 #endif
00539 if (user == RSBAC_NO_USER) {
00540 user = CONFIG_RSBAC_UM_USER_MIN;
00541 while (rsbac_ta_list_lol_exist
00542 (ta_number, user_handle, &user))
00543 user++;
00544 } else
00545 if (rsbac_ta_list_lol_exist
00546 (ta_number, user_handle, &user))
00547 return -RSBAC_EEXISTS;
00548 rsbac_pr_debug(aef_um, "pid %u/%.15s: adding user %u\n",
00549 current->pid, current->comm, user);
00550 if (pass) {
00551 __u32 salt;
00552
00553 new_salt(&salt);
00554 err = rsbac_um_hash(pass, salt);
00555 if (err)
00556 return err;
00557 memcpy(entry_p->pass, &salt, sizeof(salt));
00558 memcpy(entry_p->pass + sizeof(salt), pass,
00559 RSBAC_UM_PASS_LEN - sizeof(salt));
00560 } else
00561 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
00562 err =
00563 rsbac_ta_list_lol_add_ttl(ta_number,
00564 user_handle, ttl,
00565 &user, entry_p);
00566 if (!err)
00567 *user_p = user;
00568 return err;
00569 }
00570
00571 int rsbac_um_add_group(rsbac_list_ta_number_t ta_number,
00572 rsbac_gid_t * group_p,
00573 struct rsbac_um_group_entry_t *entry_p,
00574 char *pass, rsbac_time_t ttl)
00575 {
00576 int err;
00577
00578 if (!rsbac_is_initialized()) {
00579 rsbac_printk(KERN_WARNING "rsbac_um_add_group(): RSBAC not initialized\n");
00580 return (-RSBAC_ENOTINITIALIZED);
00581 }
00582 if (!entry_p)
00583 return -RSBAC_EINVALIDPOINTER;
00584 if (!rsbac_um_get_gid(ta_number, entry_p->name, group_p))
00585 return -RSBAC_EEXISTS;
00586 if (*group_p == RSBAC_NO_USER) {
00587 *group_p = CONFIG_RSBAC_UM_GROUP_MIN;
00588 while (rsbac_ta_list_exist
00589 (ta_number, group_handle,
00590 group_p))
00591 (*group_p)++;
00592 } else
00593 if (rsbac_ta_list_exist
00594 (ta_number, group_handle, group_p))
00595 return -RSBAC_EEXISTS;
00596 rsbac_pr_debug(aef_um, "pid %u/%.15s: adding group %u\n",
00597 current->pid, current->comm, *group_p);
00598 if (pass) {
00599 __u32 salt;
00600
00601 new_salt(&salt);
00602 err = rsbac_um_hash(pass, salt);
00603 if (err)
00604 return err;
00605 memcpy(entry_p->pass, &salt, sizeof(salt));
00606 memcpy(entry_p->pass + sizeof(salt), pass,
00607 RSBAC_UM_PASS_LEN - sizeof(salt));
00608 } else
00609 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
00610 return rsbac_ta_list_add_ttl(ta_number,
00611 group_handle,
00612 ttl, group_p, entry_p);
00613 }
00614
00615 int rsbac_um_add_gm(rsbac_list_ta_number_t ta_number,
00616 rsbac_uid_t user, rsbac_gid_t group, rsbac_time_t ttl)
00617 {
00618 if (!rsbac_is_initialized()) {
00619 rsbac_printk(KERN_WARNING "rsbac_um_add_gm(): RSBAC not initialized\n");
00620 return (-RSBAC_ENOTINITIALIZED);
00621 }
00622 #ifdef CONFIG_RSBAC_UM_EXCL
00623 if (!rsbac_um_no_excl) {
00624 if (!rsbac_ta_list_exist
00625 (ta_number, user_handle, &user)) {
00626 rsbac_printk(KERN_INFO "rsbac_um_add_gm(): uid %u not known to RSBAC User Management!\n",
00627 user);
00628 return -RSBAC_ENOTFOUND;
00629 }
00630 if (!rsbac_ta_list_exist
00631 (ta_number, group_handle, &group)) {
00632 rsbac_printk(KERN_INFO "rsbac_um_add_gm(): gid %u not known to RSBAC User Management!\n",
00633 group);
00634 return -RSBAC_ENOTFOUND;
00635 }
00636 }
00637 #endif
00638 rsbac_pr_debug(aef_um, "pid %u/%.15s: adding user %u group %u\n",
00639 current->pid, current->comm, user, group);
00640 return rsbac_ta_list_lol_subadd_ttl(ta_number,
00641 user_handle,
00642 ttl, &user, &group, NULL);
00643 }
00644
00645 int rsbac_um_mod_user(rsbac_list_ta_number_t ta_number,
00646 rsbac_uid_t user,
00647 enum rsbac_um_mod_t mod,
00648 union rsbac_um_mod_data_t *data_p)
00649 {
00650 int err;
00651 struct rsbac_um_user_entry_t *entry_p;
00652
00653 if (!rsbac_is_initialized()) {
00654 rsbac_printk(KERN_WARNING "rsbac_um_mod_user(): RSBAC not initialized\n");
00655 return (-RSBAC_ENOTINITIALIZED);
00656 }
00657 if (!data_p && (mod != UM_pass)
00658 )
00659 return -RSBAC_EINVALIDPOINTER;
00660 if (!rsbac_ta_list_lol_exist
00661 (ta_number, user_handle, &user))
00662 return -RSBAC_ENOTFOUND;
00663
00664 entry_p = rsbac_kmalloc(sizeof(*entry_p));
00665 if (!entry_p)
00666 return -RSBAC_ENOMEM;
00667 err =
00668 rsbac_ta_list_lol_get_data_ttl(ta_number,
00669 user_handle,
00670 NULL, &user, entry_p);
00671 if (err) {
00672 rsbac_kfree(entry_p);
00673 return err;
00674 }
00675 rsbac_pr_debug(aef_um, "pid %u/%.15s: modifying user %u\n",
00676 current->pid, current->comm, user);
00677 switch (mod) {
00678 case UM_name:
00679 {
00680 rsbac_uid_t tmp_user;
00681
00682 if (!rsbac_um_get_uid
00683 (ta_number, data_p->string, &tmp_user)
00684 && (tmp_user != user)
00685 )
00686 return -RSBAC_EEXISTS;
00687 strncpy(entry_p->name, data_p->string,
00688 RSBAC_UM_NAME_LEN);
00689 entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
00690 }
00691 break;
00692
00693 case UM_pass:
00694 if (data_p) {
00695 __u32 salt;
00696
00697 new_salt(&salt);
00698 err = rsbac_um_hash(data_p->string, salt);
00699 if (err) {
00700 rsbac_kfree(entry_p);
00701 return err;
00702 }
00703 memcpy(entry_p->pass, &salt, sizeof(salt));
00704 memcpy(entry_p->pass + sizeof(salt),
00705 data_p->string,
00706 RSBAC_UM_PASS_LEN - sizeof(salt));
00707 } else
00708 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
00709 entry_p->lastchange = RSBAC_CURRENT_TIME / 86400;
00710 break;
00711
00712 case UM_cryptpass:
00713 memcpy(entry_p->pass, data_p->string, RSBAC_UM_PASS_LEN);
00714 break;
00715
00716 case UM_fullname:
00717 strncpy(entry_p->fullname, data_p->string,
00718 RSBAC_UM_FULLNAME_LEN);
00719 entry_p->fullname[RSBAC_UM_FULLNAME_LEN - 1] = 0;
00720 break;
00721
00722 case UM_homedir:
00723 strncpy(entry_p->homedir, data_p->string,
00724 RSBAC_UM_HOMEDIR_LEN);
00725 entry_p->homedir[RSBAC_UM_HOMEDIR_LEN - 1] = 0;
00726 break;
00727
00728 case UM_shell:
00729 strncpy(entry_p->shell, data_p->string,
00730 RSBAC_UM_SHELL_LEN);
00731 entry_p->shell[RSBAC_UM_SHELL_LEN - 1] = 0;
00732 break;
00733
00734 case UM_group:
00735 #ifdef CONFIG_RSBAC_UM_EXCL
00736 if (!rsbac_um_no_excl
00737 && !rsbac_ta_list_exist(ta_number,
00738 group_handle,
00739 &data_p->group)) {
00740 rsbac_printk(KERN_INFO "rsbac_um_mod_user(): gid %u not known to RSBAC User Management!\n",
00741 data_p->group);
00742 rsbac_kfree(entry_p);
00743 return -RSBAC_EINVALIDVALUE;
00744 }
00745 #endif
00746 entry_p->group = data_p->group;
00747 break;
00748
00749 case UM_lastchange:
00750 entry_p->lastchange = data_p->days;
00751 break;
00752
00753 case UM_minchange:
00754 entry_p->minchange = data_p->days;
00755 break;
00756
00757 case UM_maxchange:
00758 entry_p->maxchange = data_p->days;
00759 break;
00760
00761 case UM_warnchange:
00762 entry_p->warnchange = data_p->days;
00763 break;
00764
00765 case UM_inactive:
00766 entry_p->inactive = data_p->days;
00767 break;
00768
00769 case UM_expire:
00770 entry_p->expire = data_p->days;
00771 break;
00772
00773 case UM_ttl:
00774 err =
00775 rsbac_ta_list_lol_add_ttl(ta_number,
00776 user_handle,
00777 data_p->ttl, &user, entry_p);
00778 rsbac_kfree(entry_p);
00779 return err;
00780
00781 default:
00782 rsbac_kfree(entry_p);
00783 return -RSBAC_EINVALIDREQUEST;
00784 }
00785
00786 err =
00787 rsbac_ta_list_lol_add_ttl(ta_number,
00788 user_handle,
00789 RSBAC_LIST_TTL_KEEP, &user, entry_p);
00790 rsbac_kfree(entry_p);
00791 return err;
00792 }
00793
00794 int rsbac_um_mod_group(rsbac_list_ta_number_t ta_number,
00795 rsbac_uid_t group,
00796 enum rsbac_um_mod_t mod,
00797 union rsbac_um_mod_data_t *data_p)
00798 {
00799 int err;
00800 struct rsbac_um_group_entry_t *entry_p;
00801
00802 if (!rsbac_is_initialized()) {
00803 rsbac_printk(KERN_WARNING "rsbac_um_mod_group(): RSBAC not initialized\n");
00804 return (-RSBAC_ENOTINITIALIZED);
00805 }
00806 if (!data_p && (mod != UM_pass)
00807 )
00808 return -RSBAC_EINVALIDPOINTER;
00809 if (!rsbac_ta_list_exist
00810 (ta_number, group_handle, &group))
00811 return -RSBAC_ENOTFOUND;
00812
00813 entry_p = rsbac_kmalloc(sizeof(*entry_p));
00814 if (!entry_p)
00815 return -RSBAC_ENOMEM;
00816 err =
00817 rsbac_ta_list_get_data_ttl(ta_number,
00818 group_handle,
00819 NULL, &group, entry_p);
00820 if (err) {
00821 rsbac_kfree(entry_p);
00822 return err;
00823 }
00824 rsbac_pr_debug(aef_um, "pid %u/%.15s: modifying group %u\n",
00825 current->pid, current->comm, group);
00826 switch (mod) {
00827 case UM_name:
00828 {
00829 rsbac_gid_t tmp_group;
00830
00831 if (!rsbac_um_get_gid
00832 (ta_number, data_p->string, &tmp_group)
00833 && (tmp_group != group)
00834 )
00835 return -RSBAC_EEXISTS;
00836 strncpy(entry_p->name, data_p->string,
00837 RSBAC_UM_NAME_LEN);
00838 entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
00839 }
00840 break;
00841
00842 case UM_pass:
00843 if (data_p) {
00844 __u32 salt;
00845
00846 new_salt(&salt);
00847 err = rsbac_um_hash(data_p->string, salt);
00848 if (err) {
00849 rsbac_kfree(entry_p);
00850 return err;
00851 }
00852 memcpy(entry_p->pass, &salt, sizeof(salt));
00853 memcpy(entry_p->pass + sizeof(salt),
00854 data_p->string,
00855 RSBAC_UM_PASS_LEN - sizeof(salt));
00856 } else
00857 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
00858 break;
00859
00860 case UM_cryptpass:
00861 memcpy(entry_p->pass, data_p->string, RSBAC_UM_PASS_LEN);
00862 break;
00863
00864 case UM_ttl:
00865 err =
00866 rsbac_ta_list_add_ttl(ta_number,
00867 group_handle,
00868 data_p->ttl, &group, entry_p);
00869 rsbac_kfree(entry_p);
00870 return err;
00871
00872 default:
00873 rsbac_kfree(entry_p);
00874 return -RSBAC_EINVALIDREQUEST;
00875 }
00876
00877 err =
00878 rsbac_ta_list_add_ttl(ta_number,
00879 group_handle,
00880 RSBAC_LIST_TTL_KEEP, &group, entry_p);
00881 rsbac_kfree(entry_p);
00882 return err;
00883 }
00884
00885 int rsbac_um_get_user_item(rsbac_list_ta_number_t ta_number,
00886 rsbac_uid_t user,
00887 enum rsbac_um_mod_t mod,
00888 union rsbac_um_mod_data_t *data_p)
00889 {
00890 int err;
00891 struct rsbac_um_user_entry_t *entry_p;
00892
00893 if (!rsbac_is_initialized()) {
00894 rsbac_printk(KERN_WARNING "rsbac_um_get_user_item(): RSBAC not initialized\n");
00895 return (-RSBAC_ENOTINITIALIZED);
00896 }
00897 if (!data_p)
00898 return -RSBAC_EINVALIDPOINTER;
00899 if (!rsbac_ta_list_lol_exist
00900 (ta_number, user_handle, &user))
00901 return -RSBAC_ENOTFOUND;
00902 if (mod == UM_ttl)
00903 return rsbac_ta_list_lol_get_data_ttl(ta_number,
00904 user_handle,
00905 &data_p->ttl, &user,
00906 NULL);
00907
00908 entry_p = rsbac_kmalloc(sizeof(*entry_p));
00909 if (!entry_p)
00910 return -RSBAC_ENOMEM;
00911 err =
00912 rsbac_ta_list_lol_get_data_ttl(ta_number,
00913 user_handle,
00914 NULL, &user, entry_p);
00915 if (err) {
00916 rsbac_kfree(entry_p);
00917 return err;
00918 }
00919 switch (mod) {
00920 case UM_name:
00921 strcpy(data_p->string, entry_p->name);
00922 break;
00923
00924 case UM_pass:
00925 memcpy(data_p->string, entry_p->pass, RSBAC_UM_PASS_LEN);
00926 break;
00927
00928 case UM_fullname:
00929 strcpy(data_p->string, entry_p->fullname);
00930 break;
00931
00932 case UM_homedir:
00933 strcpy(data_p->string, entry_p->homedir);
00934 break;
00935
00936 case UM_shell:
00937 strcpy(data_p->string, entry_p->shell);
00938 break;
00939
00940 case UM_group:
00941 data_p->group = entry_p->group;
00942 break;
00943
00944 case UM_lastchange:
00945 data_p->days = entry_p->lastchange;
00946 break;
00947
00948 case UM_minchange:
00949 data_p->days = entry_p->minchange;
00950 break;
00951
00952 case UM_maxchange:
00953 data_p->days = entry_p->maxchange;
00954 break;
00955
00956 case UM_warnchange:
00957 data_p->days = entry_p->warnchange;
00958 break;
00959
00960 case UM_inactive:
00961 data_p->days = entry_p->inactive;
00962 break;
00963
00964 case UM_expire:
00965 data_p->days = entry_p->expire;
00966 break;
00967
00968 default:
00969 rsbac_kfree(entry_p);
00970 return -RSBAC_EINVALIDREQUEST;
00971 }
00972
00973 rsbac_kfree(entry_p);
00974 return 0;
00975 }
00976
00977 int rsbac_um_get_group_item(rsbac_list_ta_number_t ta_number,
00978 rsbac_gid_t group,
00979 enum rsbac_um_mod_t mod,
00980 union rsbac_um_mod_data_t *data_p)
00981 {
00982 int err;
00983 struct rsbac_um_group_entry_t *entry_p;
00984
00985 if (!rsbac_is_initialized()) {
00986 rsbac_printk(KERN_WARNING "rsbac_um_get_group_item(): RSBAC not initialized\n");
00987 return (-RSBAC_ENOTINITIALIZED);
00988 }
00989 if (!data_p)
00990 return -RSBAC_EINVALIDPOINTER;
00991 if (!rsbac_ta_list_exist
00992 (ta_number, group_handle, &group))
00993 return -RSBAC_ENOTFOUND;
00994 if (mod == UM_ttl)
00995 return rsbac_ta_list_get_data_ttl(ta_number,
00996 group_handle,
00997 &data_p->ttl, &group,
00998 NULL);
00999
01000 entry_p = rsbac_kmalloc(sizeof(*entry_p));
01001 if (!entry_p)
01002 return -RSBAC_ENOMEM;
01003 err =
01004 rsbac_ta_list_get_data_ttl(ta_number,
01005 group_handle,
01006 NULL, &group, entry_p);
01007 if (err) {
01008 rsbac_kfree(entry_p);
01009 return err;
01010 }
01011 switch (mod) {
01012 case UM_name:
01013 strcpy(data_p->string, entry_p->name);
01014 break;
01015
01016 case UM_pass:
01017 memcpy(data_p->string, entry_p->pass, RSBAC_UM_PASS_LEN);
01018 break;
01019
01020 default:
01021 rsbac_kfree(entry_p);
01022 return -RSBAC_EINVALIDREQUEST;
01023 }
01024
01025 rsbac_kfree(entry_p);
01026 return 0;
01027 }
01028
01029 int rsbac_um_user_exists(rsbac_list_ta_number_t ta_number,
01030 rsbac_uid_t user)
01031 {
01032 return rsbac_ta_list_lol_exist(ta_number,
01033 user_handle,
01034 &user);
01035 }
01036
01037 int rsbac_um_group_exists(rsbac_list_ta_number_t ta_number,
01038 rsbac_gid_t group)
01039 {
01040 return rsbac_ta_list_exist(ta_number,
01041 group_handle,
01042 &group);
01043 }
01044
01045 int rsbac_um_remove_user(rsbac_list_ta_number_t ta_number,
01046 rsbac_uid_t user)
01047 {
01048 if (!rsbac_ta_list_lol_exist
01049 (ta_number, user_handle, &user))
01050 return -RSBAC_ENOTFOUND;
01051 return rsbac_ta_list_lol_remove(ta_number,
01052 user_handle,
01053 &user);
01054 }
01055
01056 int rsbac_um_remove_group(rsbac_list_ta_number_t ta_number,
01057 rsbac_gid_t group)
01058 {
01059 if (!rsbac_ta_list_exist
01060 (ta_number, group_handle, &group))
01061 return -RSBAC_ENOTFOUND;
01062 rsbac_ta_list_lol_subremove_from_all(ta_number,
01063 user_handle,
01064 &group);
01065 return rsbac_ta_list_remove(ta_number,
01066 group_handle,
01067 &group);
01068 }
01069
01070 int rsbac_um_remove_gm(rsbac_list_ta_number_t ta_number,
01071 rsbac_uid_t user, rsbac_gid_t group)
01072 {
01073 if (!rsbac_is_initialized()) {
01074 rsbac_printk(KERN_WARNING "rsbac_um_remove_gm(): RSBAC not initialized\n");
01075 return (-RSBAC_ENOTINITIALIZED);
01076 }
01077 rsbac_pr_debug(aef_um, "pid %u/%.15s: removing user %u group %u\n",
01078 current->pid, current->comm, user, group);
01079 return rsbac_ta_list_lol_subremove(ta_number,
01080 user_handle,
01081 &user, &group);
01082 }
01083
01084 int rsbac_um_get_user_entry(rsbac_list_ta_number_t ta_number,
01085 rsbac_uid_t user,
01086 struct rsbac_um_user_entry_t *entry_p,
01087 rsbac_time_t * ttl_p)
01088 {
01089 return rsbac_ta_list_lol_get_data_ttl(ta_number,
01090 user_handle,
01091 ttl_p, &user, entry_p);
01092 }
01093
01094 int rsbac_um_get_next_user(rsbac_list_ta_number_t ta_number,
01095 rsbac_uid_t old_user, rsbac_uid_t * next_user_p)
01096 {
01097 rsbac_uid_t *old_user_p;
01098
01099 if (old_user == RSBAC_NO_USER)
01100 old_user_p = NULL;
01101 else
01102 old_user_p = &old_user;
01103
01104 return rsbac_ta_list_lol_get_next_desc(ta_number,
01105 user_handle,
01106 old_user_p,
01107 next_user_p);
01108 }
01109
01110 int rsbac_um_get_user_list(rsbac_list_ta_number_t ta_number,
01111 rsbac_uid_t ** list_pp)
01112 {
01113 if(!list_pp)
01114 return rsbac_ta_list_lol_count(ta_number, user_handle);
01115 else
01116 return rsbac_ta_list_lol_get_all_desc(ta_number,
01117 user_handle,
01118 (void **) list_pp);
01119 }
01120
01121 int rsbac_um_get_gm_list(rsbac_list_ta_number_t ta_number,
01122 rsbac_uid_t user, rsbac_gid_t ** list_pp)
01123 {
01124 if (!list_pp)
01125 return rsbac_ta_list_lol_subcount(ta_number,
01126 user_handle,
01127 &user);
01128 else
01129 return rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
01130 user_handle,
01131 &user,
01132 (void **) list_pp,
01133 NULL);
01134 }
01135
01136 int rsbac_um_get_gm_user_list(
01137 rsbac_list_ta_number_t ta_number,
01138 rsbac_gid_t group,
01139 rsbac_uid_t ** list_pp)
01140 {
01141 int j;
01142 long all_count = 0;
01143 long copy_count = 0;
01144 long tmp_count;
01145 rsbac_uid_t * tmp_list_p;
01146 rsbac_uid_t * collect_list_p;
01147 rsbac_uid_t * p;
01148
01149 #ifdef CONFIG_RSBAC_UM_EXCL
01150 if(!rsbac_um_no_excl && !rsbac_ta_list_exist(ta_number, group_handle, &group))
01151 {
01152 return -RSBAC_ENOTFOUND;
01153 }
01154 #endif
01155 all_count = rsbac_ta_list_lol_count(ta_number, user_handle);
01156 if(!list_pp || (all_count <= 0))
01157 return all_count;
01158
01159
01160 all_count += EXTRA_ROOM;
01161 collect_list_p = rsbac_vmalloc(all_count * sizeof(rsbac_uid_t));
01162 if(!collect_list_p)
01163 return -RSBAC_ENOMEM;
01164 p = collect_list_p;
01165 tmp_count = rsbac_ta_list_lol_get_all_desc(ta_number, user_handle, (void *) &tmp_list_p);
01166 if(tmp_count > 0)
01167 {
01168 tmp_count = rsbac_min(tmp_count, all_count - copy_count);
01169 for(j=0; j<tmp_count; j++)
01170 {
01171 if(rsbac_ta_list_lol_subexist(ta_number, user_handle, &tmp_list_p[j], &group))
01172 {
01173 *p = tmp_list_p[j];
01174 p++;
01175 copy_count++;
01176 }
01177 }
01178 rsbac_vfree(tmp_list_p);
01179 }
01180 if(!copy_count)
01181 rsbac_vfree(collect_list_p);
01182 else
01183 *list_pp = collect_list_p;
01184 return copy_count;
01185 }
01186
01187 int rsbac_um_get_group_list(rsbac_list_ta_number_t ta_number,
01188 rsbac_gid_t ** list_pp)
01189 {
01190 if(!list_pp)
01191 return rsbac_ta_list_count(ta_number, group_handle);
01192 else
01193 return rsbac_ta_list_get_all_desc(ta_number,
01194 group_handle,
01195 (void **) list_pp);
01196 }
01197
01198 int rsbac_um_check_pass(rsbac_uid_t uid, char *pass)
01199 {
01200 int err;
01201 struct rsbac_um_user_entry_t *entry_p;
01202 __u32 salt;
01203 u_long curdays;
01204
01205 if (!pass)
01206 return -RSBAC_EINVALIDPOINTER;
01207 entry_p = rsbac_kmalloc(sizeof(*entry_p));
01208 if (!entry_p)
01209 return -RSBAC_ENOMEM;
01210 err = rsbac_ta_list_lol_get_data_ttl(0, user_handle,
01211 NULL, &uid, entry_p);
01212 if (err)
01213 goto out_free;
01214
01215 rsbac_pr_debug(aef_um, "pid %u/%.15s: checking password for user %u\n",
01216 current->pid, current->comm, uid);
01217
01218 curdays = RSBAC_CURRENT_TIME / 86400;
01219 if ((curdays > entry_p->expire) && (entry_p->expire != -1)
01220 && (entry_p->expire != 0) && (entry_p->lastchange != 0)) {
01221 err = -RSBAC_EEXPIRED;
01222 rsbac_pr_debug(aef_um, "pid %u/%.15s: account for user %u has expired\n",
01223 current->pid, current->comm, uid);
01224 goto out_free;
01225 }
01226 if ((curdays >
01227 (entry_p->lastchange + entry_p->maxchange +
01228 entry_p->inactive))
01229 && (entry_p->maxchange != -1)
01230 && (entry_p->maxchange)
01231 && (entry_p->inactive != -1)
01232 && (entry_p->inactive)
01233 && (entry_p->lastchange)
01234 ) {
01235 err = -RSBAC_EEXPIRED;
01236 rsbac_pr_debug(aef_um, "pid %u/%.15s: password for user %u has expired\n",
01237 current->pid, current->comm, uid);
01238 goto out_free;
01239 }
01240
01241 salt = *((__u32 *) entry_p->pass);
01242 if (!salt) {
01243 err = -EPERM;
01244 goto out_free;
01245 }
01246 err = rsbac_um_hash(pass, salt);
01247 if (err)
01248 return err;
01249 if (memcmp
01250 (pass, entry_p->pass + sizeof(salt),
01251 RSBAC_UM_PASS_LEN - sizeof(salt)))
01252 err = -EPERM;
01253 else
01254 err = 0;
01255
01256 out_free:
01257 rsbac_kfree(entry_p);
01258 if (err)
01259 ssleep(1);
01260 return err;
01261 }
01262
01263 int rsbac_um_good_pass(rsbac_uid_t uid, char *pass)
01264 {
01265 #ifdef CONFIG_RSBAC_UM_NON_ALPHA
01266 char *p;
01267 #endif
01268 #ifdef CONFIG_RSBAC_UM_PWHISTORY
01269 int i;
01270 long count;
01271 char *hist_pass;
01272 char *tmp;
01273 __u8 *pwhistory_array;
01274 __u32 salt;
01275 #endif
01276
01277 if (!pass)
01278 return -RSBAC_EINVALIDPOINTER;
01279 if (strlen(pass) < CONFIG_RSBAC_UM_MIN_PASS_LEN)
01280 return -RSBAC_EWEAKPASSWORD;
01281
01282 #ifdef CONFIG_RSBAC_UM_NON_ALPHA
01283 p = pass;
01284 while (*p && (((*p >= 'a')
01285 && (*p <= 'z')
01286 )
01287 || ((*p >= 'A')
01288 && (*p <= 'Z')
01289 )
01290 )
01291 )
01292 p++;
01293 if (!(*p))
01294 return -RSBAC_EWEAKPASSWORD;
01295 #endif
01296
01297 #ifdef CONFIG_RSBAC_UM_PWHISTORY
01298 count = rsbac_ta_list_lol_get_all_subdata(0,
01299 user_pwhistory_handle,
01300 &uid,
01301 (void **) &pwhistory_array);
01302 if (count > 0) {
01303 tmp =
01304 rsbac_kmalloc(rsbac_max
01305 (strlen(pass), RSBAC_UM_PASS_LEN));
01306 hist_pass = pwhistory_array;
01307
01308 for (i = 0; i < count; i++) {
01309 salt = *((__u32 *) hist_pass);
01310 memcpy(tmp, pass,
01311 rsbac_max(strlen(pass), RSBAC_UM_PASS_LEN));
01312 rsbac_um_hash(tmp, salt);
01313
01314 if (memcmp
01315 (tmp, hist_pass + sizeof(salt),
01316 RSBAC_UM_PASS_LEN - sizeof(salt)) == 0) {
01317 rsbac_kfree(tmp);
01318 rsbac_vfree(pwhistory_array);
01319 return -RSBAC_EWEAKPASSWORD;
01320 }
01321 hist_pass += RSBAC_UM_PASS_LEN;
01322 }
01323 rsbac_kfree(tmp);
01324 rsbac_vfree(pwhistory_array);
01325 }
01326 #endif
01327
01328 return 0;
01329 }
01330
01331 int rsbac_um_set_pass(rsbac_uid_t uid, char *pass)
01332 {
01333 int err;
01334 struct rsbac_um_user_entry_t *entry_p;
01335 __u32 salt;
01336
01337 entry_p = rsbac_kmalloc(sizeof(*entry_p));
01338 if (!entry_p)
01339 return -RSBAC_ENOMEM;
01340 err =
01341 rsbac_ta_list_lol_get_data_ttl(0, user_handle,
01342 NULL, &uid, entry_p);
01343 if (err)
01344 goto out_free;
01345
01346 rsbac_pr_debug(aef_um, "pid %u/%.15s: setting password for user %u\n",
01347 current->pid, current->comm, uid);
01348 if (pass) {
01349 #ifdef CONFIG_RSBAC_UM_PWHISTORY
01350 __u32 max_index = 0;
01351 __u8 max_history = CONFIG_RSBAC_UM_PWHISTORY_MAX;
01352 long count;
01353 #endif
01354 new_salt(&salt);
01355 err = rsbac_um_hash(pass, salt);
01356 if (err)
01357 goto out_free;
01358 memcpy(entry_p->pass, &salt, sizeof(salt));
01359 memcpy(entry_p->pass + sizeof(salt), pass,
01360 RSBAC_UM_PASS_LEN - sizeof(salt));
01361 #ifdef CONFIG_RSBAC_UM_PWHISTORY
01362 rsbac_ta_list_lol_get_max_subdesc(0,
01363 user_pwhistory_handle,
01364 &uid,
01365 &max_index);
01366 max_index++;
01367
01368 if (max_index != 0)
01369 rsbac_list_lol_subadd(user_pwhistory_handle,
01370 &uid, &max_index,
01371 entry_p->pass);
01372 else
01373 rsbac_printk(KERN_WARNING "rsbac_um_set_pass(): maximum password history index reached for user %u, password will not be stored!\n",
01374 uid);
01375
01376 rsbac_list_lol_get_data(user_pwhistory_handle,
01377 &uid,
01378 &max_history);
01379 count =
01380 rsbac_list_lol_subcount(user_pwhistory_handle,
01381 &uid);
01382 if (count > max_history)
01383 rsbac_ta_list_lol_subremove_count(0,
01384 user_pwhistory_handle,
01385 &uid,
01386 (count - max_history));
01387 #endif
01388 } else
01389 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
01390 entry_p->lastchange = RSBAC_CURRENT_TIME / 86400;
01391 err = rsbac_ta_list_lol_add_ttl(0, user_handle,
01392 0, &uid, entry_p);
01393
01394 out_free:
01395 rsbac_kfree(entry_p);
01396 return err;
01397 }
01398
01399 int rsbac_um_set_group_pass(rsbac_gid_t gid, char *pass)
01400 {
01401 int err;
01402 struct rsbac_um_group_entry_t *entry_p;
01403 __u32 salt;
01404
01405 entry_p = rsbac_kmalloc(sizeof(*entry_p));
01406 if (!entry_p)
01407 return -RSBAC_ENOMEM;
01408 err = rsbac_ta_list_get_data_ttl(0, group_handle,
01409 NULL, &gid, entry_p);
01410 if (err)
01411 goto out_free;
01412
01413 rsbac_pr_debug(aef_um, "pid %u/%.15s: setting password for group %u\n",
01414 current->pid, current->comm, gid);
01415 if (pass) {
01416 new_salt(&salt);
01417 err = rsbac_um_hash(pass, salt);
01418 if (err)
01419 goto out_free;
01420 memcpy(entry_p->pass, &salt, sizeof(salt));
01421 memcpy(entry_p->pass + sizeof(salt), pass,
01422 RSBAC_UM_PASS_LEN - sizeof(salt));
01423 } else
01424 memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
01425 err =
01426 rsbac_ta_list_add_ttl(0, group_handle, 0,
01427 &gid, entry_p);
01428
01429 out_free:
01430 rsbac_kfree(entry_p);
01431 return err;
01432 }
01433
01434 int rsbac_um_check_account(rsbac_uid_t uid)
01435 {
01436 int err;
01437 struct rsbac_um_user_entry_t *entry_p;
01438 u_long curdays;
01439
01440 entry_p = rsbac_kmalloc(sizeof(*entry_p));
01441 if (!entry_p)
01442 return -RSBAC_ENOMEM;
01443 err =
01444 rsbac_ta_list_lol_get_data_ttl(0, user_handle,
01445 NULL, &uid, entry_p);
01446 if (err)
01447 goto out_free;
01448
01449 rsbac_pr_debug(aef_um, "pid %u/%.15s: checking account for user %u\n",
01450 current->pid, current->comm, uid);
01451
01452 curdays = RSBAC_CURRENT_TIME / 86400;
01453 if (*((__u32 *) entry_p->pass)
01454 && !entry_p->lastchange) {
01455 err = -RSBAC_EMUSTCHANGE;
01456 rsbac_pr_debug(aef_um, "pid %u/%.15s: user %u must change password, "
01457 "lastchange = 0\n", current->pid, current->comm, uid);
01458 goto out_free;
01459 }
01460 if ((curdays > entry_p->expire)
01461 && (entry_p->expire != -1)
01462 && (entry_p->expire)
01463 ) {
01464 err = -RSBAC_EEXPIRED;
01465 rsbac_pr_debug(aef_um, "pid %u/%.15s: account for user %u has expired\n",
01466 current->pid, current->comm, uid);
01467 goto out_free;
01468 }
01469 if ((curdays >
01470 (entry_p->lastchange + entry_p->maxchange +
01471 entry_p->inactive))
01472 && (entry_p->maxchange != -1)
01473 && (entry_p->maxchange)
01474 && (entry_p->inactive != -1)
01475 && (entry_p->inactive)
01476 ) {
01477 err = -RSBAC_EEXPIRED;
01478 rsbac_pr_debug(aef_um, "pid %u/%.15s: password for user %u has expired\n",
01479 current->pid, current->comm, uid);
01480 goto out_free;
01481 }
01482 if (((entry_p->lastchange + entry_p->maxchange) < curdays)
01483 && entry_p->maxchange && (entry_p->maxchange != -1)
01484 ) {
01485 err = -RSBAC_EMUSTCHANGE;
01486 rsbac_pr_debug(aef_um, "pid %u/%.15s: user %u must change password, "
01487 "lastchange too old\n",
01488 current->pid, current->comm, uid);
01489 goto out_free;
01490 }
01491 if ((curdays >
01492 (entry_p->lastchange + entry_p->maxchange -
01493 entry_p->warnchange))
01494 && (entry_p->maxchange != -1)
01495 && (entry_p->warnchange != -1)
01496 && entry_p->maxchange && entry_p->warnchange) {
01497 err = (entry_p->lastchange + entry_p->maxchange) - curdays;
01498 } else
01499 err = 0;
01500
01501 out_free:
01502 rsbac_kfree(entry_p);
01503 return err;
01504 }