1
/* Copyright (C) 2000-2002, 2004 Red Hat, Inc.
3
* This is free software; you can redistribute it and/or modify it under
4
* the terms of the GNU Library General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
8
* This program is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
* General Public License for more details.
13
* You should have received a copy of the GNU Library General Public
14
* License along with this program; if not, write to the Free Software
15
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
#ident "$Id: user.c,v 1.78 2005/09/12 23:24:37 mitr Exp $"
21
#include "../config.h"
23
#include <sys/types.h>
33
#include "user_private.h"
36
#define DEFAULT_ID 500
39
uses_elevated_privileges = 0x0003,
54
users_enumerate_by_group,
56
users_enumerate_by_group_full,
66
group_unlock_nonempty,
71
groups_enumerate_full,
72
groups_enumerate_by_user,
73
groups_enumerate_by_user_full,
77
lu_start(const char *auth_name, enum lu_entity_type auth_type,
78
const char *modules, const char *create_modules,
79
lu_prompt_fn *prompter, gpointer prompter_data,
80
struct lu_error **error)
82
struct lu_context *ctx = NULL;
84
LU_ERROR_CHECK(error);
86
/* Register our message domain with gettext. */
87
bindtextdomain(PACKAGE, LOCALEDIR);
89
/* Initialize the gtype system if it's not already initialized. */
92
/* Allocate space for the context. */
93
ctx = g_malloc0(sizeof(struct lu_context));
95
/* Create a configuration structure. */
96
if (lu_cfg_init(ctx, error) == FALSE) {
97
/* If there's an error, lu_cfg_init() sets it. */
102
/* Initialize the rest of the fields. */
103
ctx->scache = lu_string_cache_new(TRUE);
105
ctx->auth_name = ctx->scache->cache(ctx->scache, auth_name);
106
ctx->auth_type = auth_type;
108
ctx->prompter = prompter;
109
ctx->prompter_data = prompter_data;
111
ctx->modules = g_tree_new(lu_strcasecmp);
113
/* Read the list of default modules, if the application didn't specify
114
* any that we should be using. */
115
if (modules == NULL) {
116
modules = lu_cfg_read_single(ctx,
120
if (create_modules == NULL) {
121
create_modules = lu_cfg_read_single(ctx,
122
"defaults/create_modules",
126
/* Load the modules. */
127
if (!lu_modules_load(ctx, modules, &ctx->module_names, error)) {
128
/* lu_module_load sets errors */
132
if (!lu_modules_load(ctx, create_modules, &ctx->create_module_names,
134
/* lu_module_load sets errors */
143
lu_end(struct lu_context *context)
145
g_assert(context != NULL);
147
if (context->modules != NULL) {
148
g_tree_foreach(context->modules, lu_module_unload, NULL);
149
g_tree_destroy(context->modules);
152
g_value_array_free(context->create_module_names);
153
g_value_array_free(context->module_names);
155
lu_cfg_done(context);
157
if (context->scache != NULL) {
158
context->scache->free(context->scache);
161
memset(context, 0, sizeof(struct lu_context));
167
extract_name(struct lu_ent *ent)
171
g_return_val_if_fail(ent != NULL, NULL);
172
g_return_val_if_fail((ent->type == lu_user) || (ent->type == lu_group), NULL);
173
array = lu_ent_get(ent,
174
ent->type == lu_user ? LU_USERNAME : LU_GROUPNAME);
176
array = lu_ent_get_current(ent,
177
ent->type == lu_user ? LU_USERNAME : LU_GROUPNAME);
179
g_return_val_if_fail(array != NULL, NULL);
180
value = g_value_array_get_nth(array, 0);
181
g_return_val_if_fail(value != NULL, NULL);
182
return ent->cache->cache(ent->cache, g_value_get_string(value));
186
lu_name_allowed(struct lu_ent *ent, struct lu_error **error)
191
g_return_val_if_fail(ent != NULL, FALSE);
192
g_return_val_if_fail((ent->type == lu_user) || (ent->type == lu_group),
194
sdata = extract_name(ent);
196
lu_error_new(error, lu_error_name_bad, _("name is not set"));
201
lu_error_new(error, lu_error_name_bad, _("name is too short"));
204
if (len > UT_NAMESIZE - 1) {
205
lu_error_new(error, lu_error_name_bad,
206
_("name is too long (%zu > %d)"), len,
210
for (i = 0; sdata[i] != '\0'; i++) {
211
if ((sdata[i] & 0x80) != 0) {
212
lu_error_new(error, lu_error_name_bad,
213
_("name contains non-ASCII characters"));
217
for (i = 0; sdata[i] != '\0'; i++) {
218
if ((sdata[i] == 0x7f) || (sdata[i] < 0x20)) {
219
lu_error_new(error, lu_error_name_bad,
220
_("name contains control characters"));
224
for (i = 0; sdata[i] != '\0'; i++) {
225
if (g_ascii_isspace(sdata[i])) {
226
lu_error_new(error, lu_error_name_bad,
227
_("name contains whitespace"));
231
/* SUSv3 (3.426) says "To be portable across ..., the value is composed
232
of characters from the portable filename character set. The hyphen
233
should not be used as the first character of a portable user name.
235
Note: "the value _is_ composed", not "should be" composed. We don't
236
have to allow more. */
237
if (sdata[0] == '-') {
238
lu_error_new(error, lu_error_name_bad,
239
_("name starts with a hyphen"));
242
for (i = 0; sdata[i] != '\0'; i++) {
243
if (!((sdata[i] >= 'a' && sdata[i] <= 'z')
244
|| (sdata[i] >= 'A' && sdata[i] <= 'Z')
245
|| (sdata[i] >= '0' && sdata[i] <= '9')
246
|| sdata[i] == '.' || sdata[i] == '-' || sdata[i] == '_'
247
/* Allow trailing $ for samba machine accounts. */
248
|| (sdata[i] == '$' && sdata[i + 1] == '\0'))) {
249
lu_error_new(error, lu_error_name_bad,
250
_("name contains invalid char `%c'"),
259
extract_id(struct lu_ent *ent)
264
g_return_val_if_fail(ent != NULL, LU_VALUE_INVALID_ID);
265
g_return_val_if_fail((ent->type == lu_user) || (ent->type == lu_group),
266
LU_VALUE_INVALID_ID);
267
array = lu_ent_get(ent,
268
ent->type == lu_user ? LU_UIDNUMBER : LU_GIDNUMBER);
270
array = lu_ent_get_current(ent,
271
ent->type == lu_user ? LU_UIDNUMBER : LU_GIDNUMBER);
273
g_return_val_if_fail(array != NULL, LU_VALUE_INVALID_ID);
274
value = g_value_array_get_nth(array, 0);
275
g_return_val_if_fail(value != NULL, LU_VALUE_INVALID_ID);
276
return lu_value_get_id(value);
280
convert_user_name_to_id(struct lu_context *context, const char *sdata)
283
uid_t ret = LU_VALUE_INVALID_ID;
284
char buf[LINE_MAX * 4];
285
struct passwd *err, passwd;
286
struct lu_error *error = NULL;
287
if ((getpwnam_r(sdata, &passwd, buf, sizeof(buf), &err) == 0) &&
289
return passwd.pw_uid;
291
if (lu_user_lookup_name(context, sdata, ent, &error) == TRUE) {
292
ret = extract_id(ent);
299
convert_group_name_to_id(struct lu_context *context, const char *sdata)
302
gid_t ret = LU_VALUE_INVALID_ID;
303
char buf[LINE_MAX * 4];
304
struct group *err, group;
305
struct lu_error *error = NULL;
306
if ((getgrnam_r(sdata, &group, buf, sizeof(buf), &err) == 0) &&
310
if (lu_group_lookup_name(context, sdata, ent, &error) == TRUE) {
311
ret = extract_id(ent);
317
static gboolean lu_refresh_int(struct lu_context *context,
318
struct lu_ent *entity,
319
struct lu_error **error);
322
lu_refresh_user(struct lu_context *context, struct lu_ent *entity,
323
struct lu_error **error)
325
g_return_val_if_fail(entity->type == lu_user, FALSE);
326
return lu_refresh_int(context, entity, error);
330
lu_refresh_group(struct lu_context *context, struct lu_ent *entity,
331
struct lu_error **error)
333
g_return_val_if_fail(entity->type == lu_group, FALSE);
334
return lu_refresh_int(context, entity, error);
338
run_single(struct lu_context *context,
339
struct lu_module *module,
340
enum lu_dispatch_id id,
341
const char *sdata, id_t ldata,
342
struct lu_ent *entity,
344
struct lu_error **error)
349
g_assert(context != NULL);
350
g_assert(module != NULL);
352
LU_ERROR_CHECK(error);
355
case user_lookup_name:
356
g_return_val_if_fail(sdata != NULL, FALSE);
357
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
358
g_return_val_if_fail(entity != NULL, FALSE);
359
if (module->user_lookup_name(module, sdata, entity, error)) {
360
lu_ent_add_module(entity, module->name);
365
g_return_val_if_fail(entity != NULL, FALSE);
366
if (module->user_lookup_id(module, ldata, entity, error)) {
367
lu_ent_add_module(entity, module->name);
372
g_return_val_if_fail(entity != NULL, FALSE);
373
if (module->user_default(module, sdata, ldata, entity, error)) {
374
lu_ent_add_module(entity, module->name);
379
g_return_val_if_fail(entity != NULL, FALSE);
380
if (module->user_add(module, entity, error)) {
381
lu_ent_add_module(entity, module->name);
386
g_return_val_if_fail(entity != NULL, FALSE);
387
if (lu_name_allowed(entity, error) == FALSE) {
389
} else if (module->user_add_prep(module, entity, error)) {
390
lu_ent_add_module(entity, module->name);
395
g_return_val_if_fail(entity != NULL, FALSE);
396
return module->user_mod(module, entity, error);
398
g_return_val_if_fail(entity != NULL, FALSE);
399
return module->user_del(module, entity, error);
401
g_return_val_if_fail(entity != NULL, FALSE);
402
return module->user_lock(module, entity, error);
404
g_return_val_if_fail(entity != NULL, FALSE);
405
return module->user_unlock(module, entity, error);
406
case user_unlock_nonempty:
407
g_return_val_if_fail(entity != NULL, FALSE);
408
return module->user_unlock_nonempty(module, entity, error);
410
g_return_val_if_fail(entity != NULL, FALSE);
411
return module->user_is_locked(module, entity, error);
413
g_return_val_if_fail(entity != NULL, FALSE);
414
g_return_val_if_fail(sdata != NULL, FALSE);
415
return module->user_setpass(module, entity, sdata, error);
416
case user_removepass:
417
g_return_val_if_fail(entity != NULL, FALSE);
418
return module->user_removepass(module, entity, error);
419
case users_enumerate:
420
g_return_val_if_fail(ret != NULL, FALSE);
421
*ret = module->users_enumerate(module, sdata, error);
423
case users_enumerate_by_group:
424
g_return_val_if_fail(sdata != NULL, FALSE);
425
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
426
g_return_val_if_fail(ret != NULL, FALSE);
427
*ret = module->users_enumerate_by_group(module,
432
case users_enumerate_full:
433
g_return_val_if_fail(ret != NULL, FALSE);
434
*ret = module->users_enumerate_full(module, sdata, error);
437
for (i = 0; i < ptrs->len; i++) {
438
lu_ent_add_module(g_ptr_array_index(ptrs, i),
443
case users_enumerate_by_group_full:
444
g_return_val_if_fail(sdata != NULL, FALSE);
445
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
446
g_return_val_if_fail(ret != NULL, FALSE);
447
*ret = module->users_enumerate_by_group_full(module,
453
for (i = 0; i < ptrs->len; i++) {
454
lu_ent_add_module(g_ptr_array_index(ptrs, i),
459
case group_lookup_name:
460
g_return_val_if_fail(sdata != NULL, FALSE);
461
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
462
g_return_val_if_fail(entity != NULL, FALSE);
463
if (module->group_lookup_name(module, sdata, entity, error)) {
464
lu_ent_add_module(entity, module->name);
468
case group_lookup_id:
469
g_return_val_if_fail(entity != NULL, FALSE);
470
if (module->group_lookup_id(module, ldata, entity, error)) {
471
lu_ent_add_module(entity, module->name);
476
g_return_val_if_fail(entity != NULL, FALSE);
477
if (module->group_default(module, sdata, ldata, entity, error)) {
478
lu_ent_add_module(entity, module->name);
483
g_return_val_if_fail(entity != NULL, FALSE);
484
if (module->group_add(module, entity, error)) {
485
lu_ent_add_module(entity, module->name);
490
g_return_val_if_fail(entity != NULL, FALSE);
491
if (lu_name_allowed(entity, error) == FALSE) {
493
} else if (module->group_add_prep(module, entity, error)) {
494
lu_ent_add_module(entity, module->name);
499
g_return_val_if_fail(entity != NULL, FALSE);
500
return module->group_mod(module, entity, error);
502
g_return_val_if_fail(entity != NULL, FALSE);
503
return module->group_del(module, entity, error);
505
g_return_val_if_fail(entity != NULL, FALSE);
506
return module->group_lock(module, entity, error);
508
g_return_val_if_fail(entity != NULL, FALSE);
509
return module->group_unlock(module, entity, error);
510
case group_unlock_nonempty:
511
g_return_val_if_fail(entity != NULL, FALSE);
512
return module->group_unlock_nonempty(module, entity, error);
513
case group_is_locked:
514
g_return_val_if_fail(entity != NULL, FALSE);
515
return module->group_is_locked(module, entity, error);
517
g_return_val_if_fail(entity != NULL, FALSE);
518
g_return_val_if_fail(sdata != NULL, FALSE);
519
return module->group_setpass(module, entity, sdata, error);
520
case group_removepass:
521
g_return_val_if_fail(entity != NULL, FALSE);
522
return module->group_removepass(module, entity, error);
523
case groups_enumerate:
524
g_return_val_if_fail(ret != NULL, FALSE);
525
*ret = module->groups_enumerate(module, sdata, error);
527
case groups_enumerate_by_user:
528
g_return_val_if_fail(sdata != NULL, FALSE);
529
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
530
g_return_val_if_fail(ret != NULL, FALSE);
531
*ret = module->groups_enumerate_by_user(module,
536
case groups_enumerate_full:
537
g_return_val_if_fail(ret != NULL, FALSE);
538
*ret = module->groups_enumerate_full(module, sdata, error);
541
for (i = 0; i < ptrs->len; i++) {
542
lu_ent_add_module(g_ptr_array_index(ptrs, i),
547
case groups_enumerate_by_user_full:
548
g_return_val_if_fail(sdata != NULL, FALSE);
549
g_return_val_if_fail(strlen(sdata) > 0, FALSE);
550
g_return_val_if_fail(ret != NULL, FALSE);
551
*ret = module->groups_enumerate_by_user_full(module,
557
for (i = 0; i < ptrs->len; i++) {
558
lu_ent_add_module(g_ptr_array_index(ptrs, i),
563
case uses_elevated_privileges:
564
return module->uses_elevated_privileges(module);
566
g_assert_not_reached(); /* not reached */
572
logic_and(gboolean a, gboolean b)
578
logic_or(gboolean a, gboolean b)
584
remove_duplicate_values(GValueArray *array)
587
GValue *ivalue, *jvalue;
589
for (i = 0; i < array->n_values; i++) {
590
ivalue = g_value_array_get_nth(array, i);
591
for (j = i + 1; j < array->n_values; j++) {
592
jvalue = g_value_array_get_nth(array, j);
593
if (G_VALUE_TYPE(ivalue) == G_VALUE_TYPE(jvalue)
594
&& lu_values_equal(ivalue, jvalue)) {
595
g_value_array_remove(array, j);
603
compare_strings(gconstpointer a, gconstpointer b, gpointer data)
610
merge_ent_array_duplicates(GPtrArray *array)
612
GPtrArray *ret = NULL;
615
struct lu_ent *current, *saved;
618
GList *attributes, *list;
619
GTree *users, *groups, *tree;
620
g_return_val_if_fail(array != NULL, NULL);
621
/* We need four trees to hold the known entities. */
622
users = g_tree_new_full(compare_strings, NULL, g_free, NULL);
623
groups = g_tree_new_full(compare_strings, NULL, g_free, NULL);
624
/* A structure to hold the new list. */
625
ret = g_ptr_array_new();
626
/* Iterate over every entity in the incoming list. */
627
for (i = 0; i < array->len; i++) {
630
current = g_ptr_array_index(array, i);
634
/* Get the name of the user or group. */
635
if (current->type == lu_user) {
636
values = lu_ent_get(current, LU_USERNAME);
638
} else if (current->type == lu_group) {
639
values = lu_ent_get(current, LU_GROUPNAME);
642
g_warning("Unknown entity(%zu) type: %d.\n",
644
g_assert_not_reached();
646
value = g_value_array_get_nth(values, 0);
647
/* Convert that name or number to a quark. */
648
key = lu_value_strdup(value);
649
/* Check if there's already an entity with that name. */
650
saved = g_tree_lookup(tree, key);
651
/* If it's not in there, add this one. */
653
g_tree_insert(tree, key, current);
654
g_ptr_array_add(ret, current);
657
/* Merge all of its data into the existing one; first,
658
* the current data. */
659
attributes = lu_ent_get_attributes_current(current);
661
while (attributes != NULL) {
662
attr = (const char *)attributes->data;
663
values = lu_ent_get_current(current, attr);
664
for (j = 0; j < values->n_values; j++) {
665
value = g_value_array_get_nth(values,
667
lu_ent_add_current(saved, attr, value);
669
attributes = g_list_next(attributes);
672
/* Merge the pending data. */
673
attributes = lu_ent_get_attributes(current);
674
while (attributes != NULL) {
675
attr = (const char *)attributes->data;
676
values = lu_ent_get(current, attr);
677
for (j = 0; j < values->n_values; j++) {
678
value = g_value_array_get_nth(values,
680
lu_ent_add(saved, attr, value);
682
attributes = g_list_next(attributes);
685
/* Now merge the entity's list of modules. */
686
for (j = 0; j < current->modules->n_values; j++) {
687
value = g_value_array_get_nth(current->modules,
689
g_value_array_append(saved->modules, value);
691
remove_duplicate_values(saved->modules);
692
lu_ent_free(current);
695
g_tree_destroy(users);
696
g_tree_destroy(groups);
697
g_ptr_array_free(array, TRUE);
702
run_list(struct lu_context *context,
704
gboolean (*logic_function)(gboolean a, gboolean b),
705
enum lu_dispatch_id id,
706
const char *sdata, id_t ldata,
707
struct lu_ent *entity,
709
struct lu_error **firsterror)
711
struct lu_module *module;
712
GPtrArray *ptr_array = NULL, *tmp_ptr_array = NULL;
713
GValueArray *value_array = NULL, *tmp_value_array = NULL;
716
struct lu_ent *tmp_ent;
718
gboolean success, tsuccess;
719
struct lu_error *lasterror = NULL;
722
LU_ERROR_CHECK(firsterror);
724
g_assert(context != NULL);
725
g_assert(context->module_names != NULL);
726
g_assert(context->modules != NULL);
727
g_assert(entity != NULL);
728
g_assert(logic_function != NULL);
729
g_assert((id == user_lookup_name) ||
730
(id == user_lookup_id) ||
731
(id == user_default) ||
732
(id == user_add_prep) ||
737
(id == user_unlock) ||
738
(id == user_unlock_nonempty) ||
739
(id == user_is_locked) ||
740
(id == user_setpass) ||
741
(id == user_removepass) ||
742
(id == users_enumerate) ||
743
(id == users_enumerate_by_group) ||
744
(id == users_enumerate_full) ||
745
(id == users_enumerate_by_group_full) ||
746
(id == group_lookup_name) ||
747
(id == group_lookup_id) ||
748
(id == group_default) ||
749
(id == group_add_prep) ||
753
(id == group_lock) ||
754
(id == group_unlock) ||
755
(id == group_unlock_nonempty) ||
756
(id == group_is_locked) ||
757
(id == group_setpass) ||
758
(id == group_removepass) ||
759
(id == groups_enumerate) ||
760
(id == groups_enumerate_by_user) ||
761
(id == groups_enumerate_full) ||
762
(id == groups_enumerate_by_user_full) ||
763
(id == uses_elevated_privileges));
766
for (i = 0; i < list->n_values; i++) {
767
value = g_value_array_get_nth(list, i);
768
name = g_value_dup_string(value);
769
module = g_tree_lookup(context->modules, name);
771
g_assert(module != NULL);
773
tsuccess = run_single(context, module, id,
774
sdata, ldata, entity, &scratch,
776
if (scratch != NULL) switch (id) {
777
case users_enumerate:
778
case users_enumerate_by_group:
779
case groups_enumerate:
780
case groups_enumerate_by_user:
781
tmp_value_array = scratch;
782
value_array = *(GValueArray **)ret;
783
if (value_array == NULL) {
784
value_array = g_value_array_new(0);
786
if (tmp_value_array != NULL) {
787
for (j = 0; j < tmp_value_array->n_values; j++) {
788
value = g_value_array_get_nth(tmp_value_array,
790
g_value_array_append(value_array,
793
g_value_array_free(tmp_value_array);
795
remove_duplicate_values(value_array);
796
*(GValueArray **)ret = value_array;
798
case users_enumerate_full:
799
case users_enumerate_by_group_full:
800
case groups_enumerate_full:
801
case groups_enumerate_by_user_full:
802
/* FIXME: do some kind of merging here. */
803
tmp_ptr_array = scratch;
804
ptr_array = *(GPtrArray **)ret;
805
if (ptr_array == NULL) {
806
ptr_array = g_ptr_array_new();
808
if (tmp_ptr_array != NULL) {
809
for (j = 0; j < tmp_ptr_array->len; j++) {
810
tmp_ent = g_ptr_array_index(tmp_ptr_array,
812
g_ptr_array_add(ptr_array, tmp_ent);
814
g_ptr_array_free(tmp_ptr_array, TRUE);
816
/* remove_duplicate_ptrs(ptr_array); */
817
*(GPtrArray **)ret = ptr_array;
819
case user_lookup_name:
826
case group_lookup_name:
827
case group_lookup_id:
833
case uses_elevated_privileges:
836
g_assert_not_reached(); /* never reached */
842
success = logic_function(success, tsuccess);
844
if (firsterror != NULL) {
845
if (*firsterror == NULL) {
846
/* Make this the error we report. */
847
*firsterror = lasterror;
850
/* Already have an error, discard. */
851
if (lasterror != NULL) {
852
lu_error_free(&lasterror);
856
/* Can't report this error. */
857
if (lasterror != NULL) {
858
lu_error_free(&lasterror);
867
lu_refresh_int(struct lu_context *context, struct lu_ent *entity,
868
struct lu_error **error)
870
enum lu_dispatch_id id = 0;
873
gpointer scratch = NULL;
874
g_return_val_if_fail((entity->type == lu_user) ||
875
(entity->type == lu_group),
877
if (entity->type == lu_user) {
878
id = user_lookup_name;
880
if (entity->type == lu_group) {
881
id = group_lookup_name;
883
g_assert_not_reached();
885
sdata = extract_name(entity);
886
ldata = extract_id(entity);
887
if (run_list(context, entity->modules, logic_and, id,
888
sdata, ldata, entity, &scratch, error)) {
889
lu_ent_revert(entity);
896
lu_dispatch(struct lu_context *context,
897
enum lu_dispatch_id id,
898
const char *sdata, id_t ldata,
899
struct lu_ent *entity,
901
struct lu_error **error)
903
struct lu_ent *tmp = NULL;
905
GValueArray *values = NULL;
906
GPtrArray *ptrs = NULL;
907
GValue *value = NULL;
908
gpointer scratch = NULL;
911
LU_ERROR_CHECK(error);
913
g_assert(context != NULL);
916
if (entity != NULL) {
917
lu_ent_copy(entity, tmp);
924
case group_lookup_id:
925
/* Make sure data items are right for this call. */
927
g_assert(ldata != LU_VALUE_INVALID_ID);
929
if (run_list(context, context->module_names,
931
sdata, ldata, tmp, &scratch, error)) {
932
/* Got a match on that ID, convert it to a
933
* name and look it up by name. */
934
const char *attr = NULL;
935
if (id == user_lookup_id) {
937
id = user_lookup_name;
939
if (id == group_lookup_id) {
941
id = group_lookup_name;
943
values = lu_ent_get_current(tmp, attr);
944
if (values != NULL) {
945
value = g_value_array_get_nth(values, 0);
946
attr = g_value_get_string(value);
947
sdata = tmp->cache->cache(tmp->cache, attr);
949
/* No values for the right attribute. */
953
/* No match on that ID. */
956
/* fall through on successful ID->name conversion */
957
case user_lookup_name:
958
case group_lookup_name:
959
/* Make sure data items are right for this call. */
960
g_assert(sdata != NULL);
961
ldata = LU_VALUE_INVALID_ID;
963
if (run_list(context, context->module_names,
965
sdata, ldata, tmp, &scratch, error)) {
966
if (entity != NULL) {
968
lu_ent_copy(tmp, entity);
975
/* Make sure we have both name and boolean here. */
976
g_return_val_if_fail(sdata != NULL, FALSE);
977
/* Run the checks and preps. */
978
if (run_list(context, context->create_module_names,
980
sdata, ldata, tmp, &scratch, error)) {
981
if (entity != NULL) {
982
lu_ent_copy(tmp, entity);
989
/* Make sure we have both name and ID here. */
990
sdata = sdata ?: extract_name(tmp);
991
if (ldata == LU_VALUE_INVALID_ID)
992
ldata = extract_id(tmp);
993
g_return_val_if_fail(sdata != NULL, FALSE);
994
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
995
/* Run the checks and preps. */
996
if (run_list(context, context->create_module_names,
998
sdata, ldata, tmp, &scratch, error)) {
999
if (entity != NULL) {
1000
lu_ent_copy(tmp, entity);
1007
/* Make sure we have both name and ID here. */
1008
sdata = sdata ?: extract_name(tmp);
1009
if (ldata == LU_VALUE_INVALID_ID)
1010
ldata = extract_id(tmp);
1011
g_return_val_if_fail(sdata != NULL, FALSE);
1012
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1013
/* Add the account. */
1014
if (run_list(context, context->create_module_names,
1016
sdata, ldata, tmp, &scratch, error)) {
1017
if (entity != NULL) {
1018
lu_ent_copy(tmp, entity);
1025
/* Make sure we have both name and ID here. */
1026
/* FIXME: sdata, ldata contain new values (and are not even
1028
sdata = sdata ?: extract_name(tmp);
1029
if (ldata == LU_VALUE_INVALID_ID)
1030
ldata = extract_id(tmp);
1031
g_return_val_if_fail(sdata != NULL, FALSE);
1032
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1033
/* Make the changes. */
1034
g_assert(entity != NULL);
1035
if (run_list(context, entity->modules,
1037
sdata, ldata, tmp, &scratch, error)) {
1039
lu_ent_copy(tmp, entity);
1046
case user_unlock_nonempty:
1050
case group_unlock_nonempty:
1051
/* Make sure we have both name and ID here. */
1052
sdata = sdata ?: extract_name(tmp);
1053
if (ldata == LU_VALUE_INVALID_ID)
1054
ldata = extract_id(tmp);
1055
g_return_val_if_fail(sdata != NULL, FALSE);
1056
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1057
/* Make the changes. */
1058
g_assert(entity != NULL);
1059
if (run_list(context, entity->modules,
1061
sdata, ldata, tmp, &scratch, error)) {
1063
lu_ent_copy(tmp, entity);
1069
/* Make sure we have a valid password. */
1070
g_return_val_if_fail(sdata != NULL, FALSE);
1072
case user_removepass:
1073
case group_removepass:
1074
/* Make the changes. */
1075
g_assert(entity != NULL);
1076
if (run_list(context, entity->modules,
1078
sdata, ldata, tmp, &scratch, error)) {
1080
lu_ent_copy(tmp, entity);
1084
case user_is_locked:
1085
case group_is_locked:
1086
/* Make sure we have both name and ID here. */
1087
sdata = sdata ?: extract_name(tmp);
1088
if (ldata == LU_VALUE_INVALID_ID)
1089
ldata = extract_id(tmp);
1090
g_return_val_if_fail(sdata != NULL, FALSE);
1091
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1092
/* Run the checks. */
1093
g_assert(entity != NULL);
1094
if (run_list(context, entity->modules,
1096
sdata, ldata, tmp, &scratch, error)) {
1097
lu_ent_copy(tmp, entity);
1101
case users_enumerate_by_group:
1102
case groups_enumerate_by_user:
1103
/* Make sure we have both name and ID here. */
1104
g_return_val_if_fail(sdata != NULL, FALSE);
1105
if (id == users_enumerate_by_group) {
1106
ldata = convert_group_name_to_id(context, sdata);
1108
if (id == groups_enumerate_by_user) {
1109
ldata = convert_user_name_to_id(context, sdata);
1111
g_assert_not_reached();
1113
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1115
case users_enumerate:
1116
case groups_enumerate:
1117
/* Get the lists. */
1118
if (run_list(context, context->module_names,
1120
sdata, ldata, tmp, &values, error)) {
1121
*(GValueArray **)ret = values;
1125
case users_enumerate_by_group_full:
1126
case groups_enumerate_by_user_full:
1127
/* Make sure we have both name and ID here. */
1128
g_return_val_if_fail(sdata != NULL, FALSE);
1129
if (id == users_enumerate_by_group_full) {
1130
ldata = convert_group_name_to_id(context, sdata);
1132
if (id == groups_enumerate_by_user_full) {
1133
ldata = convert_user_name_to_id(context, sdata);
1135
g_assert_not_reached();
1137
g_return_val_if_fail(ldata != LU_VALUE_INVALID_ID, FALSE);
1139
case users_enumerate_full:
1140
case groups_enumerate_full:
1141
/* Get the lists. */
1142
if (run_list(context, context->module_names,
1144
sdata, ldata, tmp, &ptrs, error)) {
1146
for (i = 0; i < ptrs->len; i++) {
1148
ent = g_ptr_array_index(ptrs, i);
1152
*(GPtrArray **)ret = ptrs;
1155
/* Clean up results. */
1156
if (*(GPtrArray **)ret != NULL) {
1158
= merge_ent_array_duplicates(*(GPtrArray **)ret);
1161
case uses_elevated_privileges:
1162
if (run_list(context, context->module_names,
1164
sdata, ldata, tmp, &scratch, error)) {
1169
g_assert(0); /* not reached */
1176
case user_lookup_id:
1177
case user_lookup_name:
1178
g_assert(entity != NULL);
1179
entity->type = lu_user;
1181
case group_lookup_name:
1182
case group_lookup_id:
1183
g_assert(entity != NULL);
1184
entity->type = lu_group;
1189
if ((error != NULL) && (*error != NULL)) {
1190
lu_error_free(error);
1197
/* FIXME: error status, if any, is not reported to the caller */
1199
lu_uses_elevated_privileges (struct lu_context *context)
1201
struct lu_error *error = NULL;
1202
gboolean ret = lu_dispatch(context, uses_elevated_privileges, NULL, 0,
1203
NULL, NULL, &error);
1204
if (error != NULL) {
1205
lu_error_free(&error);
1211
lu_user_lookup_name(struct lu_context * context, const char *name,
1212
struct lu_ent * ent, struct lu_error ** error)
1214
LU_ERROR_CHECK(error);
1215
g_return_val_if_fail(name != NULL, FALSE);
1216
return lu_dispatch(context, user_lookup_name, name, 0,
1221
lu_group_lookup_name(struct lu_context * context, const char *name,
1222
struct lu_ent * ent, struct lu_error ** error)
1224
LU_ERROR_CHECK(error);
1225
g_return_val_if_fail(name != NULL, FALSE);
1226
return lu_dispatch(context, group_lookup_name, name, 0,
1231
lu_user_lookup_id(struct lu_context * context, uid_t uid,
1232
struct lu_ent * ent, struct lu_error ** error)
1234
LU_ERROR_CHECK(error);
1235
return lu_dispatch(context, user_lookup_id, NULL, uid,
1240
lu_group_lookup_id(struct lu_context * context, gid_t gid,
1241
struct lu_ent * ent, struct lu_error ** error)
1243
LU_ERROR_CHECK(error);
1244
return lu_dispatch(context, group_lookup_id, NULL, gid,
1249
lu_user_add(struct lu_context * context, struct lu_ent * ent,
1250
struct lu_error ** error)
1252
gboolean ret = FALSE;
1253
LU_ERROR_CHECK(error);
1255
g_return_val_if_fail(ent != NULL, FALSE);
1256
g_return_val_if_fail(ent->type == lu_user, FALSE);
1258
if (lu_dispatch(context, user_add_prep, NULL, LU_VALUE_INVALID_ID,
1259
ent, NULL, error)) {
1260
ret = lu_dispatch(context, user_add, NULL, LU_VALUE_INVALID_ID,
1261
ent, NULL, error) &&
1262
lu_refresh_user(context, ent, error);
1268
lu_group_add(struct lu_context * context, struct lu_ent * ent,
1269
struct lu_error ** error)
1271
gboolean ret = FALSE;
1272
LU_ERROR_CHECK(error);
1274
g_return_val_if_fail(ent != NULL, FALSE);
1275
g_return_val_if_fail(ent->type == lu_group, FALSE);
1277
if (lu_dispatch(context, group_add_prep, NULL, LU_VALUE_INVALID_ID,
1278
ent, NULL, error)) {
1279
ret = lu_dispatch(context, group_add, NULL,
1280
LU_VALUE_INVALID_ID, ent, NULL, error) &&
1281
lu_refresh_group(context, ent, error);
1287
lu_user_modify(struct lu_context * context, struct lu_ent * ent,
1288
struct lu_error ** error)
1290
LU_ERROR_CHECK(error);
1291
g_return_val_if_fail(ent != NULL, FALSE);
1292
g_return_val_if_fail(ent->type == lu_user, FALSE);
1293
return lu_dispatch(context, user_mod, NULL, LU_VALUE_INVALID_ID, ent,
1295
lu_refresh_user(context, ent, error);
1299
lu_group_modify(struct lu_context * context, struct lu_ent * ent,
1300
struct lu_error ** error)
1302
LU_ERROR_CHECK(error);
1303
g_return_val_if_fail(ent != NULL, FALSE);
1304
g_return_val_if_fail(ent->type == lu_group, FALSE);
1305
return lu_dispatch(context, group_mod, NULL, LU_VALUE_INVALID_ID, ent,
1307
lu_refresh_group(context, ent, error);
1311
lu_user_delete(struct lu_context * context, struct lu_ent * ent,
1312
struct lu_error ** error)
1314
LU_ERROR_CHECK(error);
1315
g_return_val_if_fail(ent != NULL, FALSE);
1316
g_return_val_if_fail(ent->type == lu_user, FALSE);
1317
return lu_dispatch(context, user_del, NULL, LU_VALUE_INVALID_ID, ent,
1322
lu_group_delete(struct lu_context * context, struct lu_ent * ent,
1323
struct lu_error ** error)
1325
LU_ERROR_CHECK(error);
1326
g_return_val_if_fail(ent != NULL, FALSE);
1327
g_return_val_if_fail(ent->type == lu_group, FALSE);
1328
return lu_dispatch(context, group_del, NULL, LU_VALUE_INVALID_ID, ent,
1333
lu_user_lock(struct lu_context * context, struct lu_ent * ent,
1334
struct lu_error ** error)
1336
LU_ERROR_CHECK(error);
1337
g_return_val_if_fail(ent != NULL, FALSE);
1338
g_return_val_if_fail(ent->type == lu_user, FALSE);
1339
return lu_dispatch(context, user_lock, NULL, LU_VALUE_INVALID_ID, ent,
1341
lu_refresh_user(context, ent, error);
1345
lu_user_unlock(struct lu_context * context, struct lu_ent * ent,
1346
struct lu_error ** error)
1348
LU_ERROR_CHECK(error);
1349
g_return_val_if_fail(ent != NULL, FALSE);
1350
g_return_val_if_fail(ent->type == lu_user, FALSE);
1351
return lu_dispatch(context, user_unlock, NULL, LU_VALUE_INVALID_ID,
1352
ent, NULL, error) &&
1353
lu_refresh_user(context, ent, error);
1357
lu_user_unlock_nonempty(struct lu_context * context, struct lu_ent * ent,
1358
struct lu_error ** error)
1360
LU_ERROR_CHECK(error);
1361
g_return_val_if_fail(ent != NULL, FALSE);
1362
g_return_val_if_fail(ent->type == lu_user, FALSE);
1363
return lu_dispatch(context, user_unlock_nonempty, NULL,
1364
LU_VALUE_INVALID_ID, ent, NULL, error) &&
1365
lu_refresh_user(context, ent, error);
1369
lu_user_islocked(struct lu_context * context, struct lu_ent * ent,
1370
struct lu_error ** error)
1372
LU_ERROR_CHECK(error);
1374
g_return_val_if_fail(ent != NULL, FALSE);
1375
g_return_val_if_fail(ent->type == lu_user, FALSE);
1377
return lu_dispatch(context, user_is_locked, NULL, LU_VALUE_INVALID_ID,
1382
lu_user_setpass(struct lu_context * context, struct lu_ent * ent,
1383
const char *password, gboolean is_crypted,
1384
struct lu_error ** error)
1388
LU_ERROR_CHECK(error);
1390
g_return_val_if_fail(ent != NULL, FALSE);
1391
g_return_val_if_fail(ent->type == lu_user, FALSE);
1394
tmp = g_strconcat(LU_CRYPTED, password, NULL);
1396
tmp = g_strdup(password);
1398
ret = lu_dispatch(context, user_setpass, tmp, LU_VALUE_INVALID_ID,
1402
ret = lu_refresh_user(context, ent, error);
1406
lu_ent_clear(ent, LU_SHADOWLASTCHANGE);
1407
memset(&value, 0, sizeof(value));
1408
g_value_init(&value, G_TYPE_STRING);
1409
g_value_set_string(&value,
1410
lu_util_shadow_current_date(ent->cache));
1411
lu_ent_add(ent, LU_SHADOWLASTCHANGE, &value);
1412
g_value_unset(&value);
1418
lu_user_removepass(struct lu_context * context, struct lu_ent * ent,
1419
struct lu_error ** error)
1422
LU_ERROR_CHECK(error);
1424
g_return_val_if_fail(ent != NULL, FALSE);
1425
g_return_val_if_fail(ent->type == lu_user, FALSE);
1427
ret = lu_dispatch(context, user_removepass, NULL, LU_VALUE_INVALID_ID,
1430
ret = lu_refresh_user(context, ent, error);
1434
lu_ent_clear(ent, LU_SHADOWLASTCHANGE);
1435
memset(&value, 0, sizeof(value));
1436
g_value_init(&value, G_TYPE_STRING);
1437
g_value_set_string(&value,
1438
lu_util_shadow_current_date(ent->cache));
1439
lu_ent_add(ent, LU_SHADOWLASTCHANGE, &value);
1440
g_value_unset(&value);
1446
lu_group_lock(struct lu_context * context, struct lu_ent * ent,
1447
struct lu_error ** error)
1449
LU_ERROR_CHECK(error);
1451
g_return_val_if_fail(ent != NULL, FALSE);
1452
g_return_val_if_fail(ent->type == lu_group, FALSE);
1454
return lu_dispatch(context, group_lock, NULL, LU_VALUE_INVALID_ID,
1455
ent, NULL, error) &&
1456
lu_refresh_group(context, ent, error);
1460
lu_group_unlock(struct lu_context * context, struct lu_ent * ent,
1461
struct lu_error ** error)
1463
LU_ERROR_CHECK(error);
1465
g_return_val_if_fail(ent != NULL, FALSE);
1466
g_return_val_if_fail(ent->type == lu_group, FALSE);
1468
return lu_dispatch(context, group_unlock, NULL, LU_VALUE_INVALID_ID,
1469
ent, NULL, error) &&
1470
lu_refresh_group(context, ent, error);
1474
lu_group_unlock_nonempty(struct lu_context * context, struct lu_ent * ent,
1475
struct lu_error ** error)
1477
LU_ERROR_CHECK(error);
1479
g_return_val_if_fail(ent != NULL, FALSE);
1480
g_return_val_if_fail(ent->type == lu_group, FALSE);
1482
return lu_dispatch(context, group_unlock_nonempty, NULL,
1483
LU_VALUE_INVALID_ID, ent, NULL, error) &&
1484
lu_refresh_group(context, ent, error);
1488
lu_group_islocked(struct lu_context * context, struct lu_ent * ent,
1489
struct lu_error ** error)
1491
LU_ERROR_CHECK(error);
1493
g_return_val_if_fail(ent != NULL, FALSE);
1494
g_return_val_if_fail(ent->type == lu_group, FALSE);
1496
return lu_dispatch(context, group_is_locked, NULL, LU_VALUE_INVALID_ID,
1501
lu_group_setpass(struct lu_context * context, struct lu_ent * ent,
1502
const char *password, gboolean is_crypted,
1503
struct lu_error ** error)
1507
LU_ERROR_CHECK(error);
1509
g_return_val_if_fail(ent != NULL, FALSE);
1510
g_return_val_if_fail(ent->type == lu_group, FALSE);
1513
tmp = g_strconcat(LU_CRYPTED, password, NULL);
1515
tmp = g_strdup(password);
1517
ret = lu_dispatch(context, group_setpass, tmp, LU_VALUE_INVALID_ID,
1521
ret = lu_refresh_group(context, ent, error);
1525
lu_ent_clear(ent, LU_SHADOWLASTCHANGE);
1526
memset(&value, 0, sizeof(value));
1527
g_value_init(&value, G_TYPE_STRING);
1528
g_value_set_string(&value,
1529
lu_util_shadow_current_date(ent->cache));
1530
lu_ent_add(ent, LU_SHADOWLASTCHANGE, &value);
1531
g_value_unset(&value);
1537
lu_group_removepass(struct lu_context * context, struct lu_ent * ent,
1538
struct lu_error ** error)
1541
LU_ERROR_CHECK(error);
1543
g_return_val_if_fail(ent != NULL, FALSE);
1544
g_return_val_if_fail(ent->type == lu_group, FALSE);
1546
ret = lu_dispatch(context, group_removepass, NULL, LU_VALUE_INVALID_ID,
1549
ret = lu_refresh_group(context, ent, error);
1553
lu_ent_clear(ent, LU_SHADOWLASTCHANGE);
1554
memset(&value, 0, sizeof(value));
1555
g_value_init(&value, G_TYPE_STRING);
1556
g_value_set_string(&value,
1557
lu_util_shadow_current_date(ent->cache));
1558
lu_ent_add(ent, LU_SHADOWLASTCHANGE, &value);
1559
g_value_unset(&value);
1565
lu_users_enumerate(struct lu_context * context, const char *pattern,
1566
struct lu_error ** error)
1568
GValueArray *ret = NULL;
1569
LU_ERROR_CHECK(error);
1570
lu_dispatch(context, users_enumerate, pattern, LU_VALUE_INVALID_ID,
1576
lu_groups_enumerate(struct lu_context * context, const char *pattern,
1577
struct lu_error ** error)
1579
GValueArray *ret = NULL;
1580
LU_ERROR_CHECK(error);
1581
lu_dispatch(context, groups_enumerate, pattern, LU_VALUE_INVALID_ID,
1587
lu_users_enumerate_by_group(struct lu_context * context, const char *group,
1588
struct lu_error ** error)
1590
GValueArray *ret = NULL;
1591
LU_ERROR_CHECK(error);
1592
lu_dispatch(context, users_enumerate_by_group, group,
1593
LU_VALUE_INVALID_ID, NULL, &ret, error);
1598
lu_groups_enumerate_by_user(struct lu_context * context, const char *user,
1599
struct lu_error ** error)
1601
GValueArray *ret = NULL;
1602
LU_ERROR_CHECK(error);
1603
lu_dispatch(context, groups_enumerate_by_user, user,
1604
LU_VALUE_INVALID_ID, NULL, &ret, error);
1609
lu_users_enumerate_full(struct lu_context * context, const char *pattern,
1610
struct lu_error ** error)
1612
GPtrArray *ret = NULL;
1613
LU_ERROR_CHECK(error);
1614
lu_dispatch(context, users_enumerate_full, pattern,
1615
LU_VALUE_INVALID_ID, NULL, &ret, error);
1620
lu_groups_enumerate_full(struct lu_context * context, const char *pattern,
1621
struct lu_error ** error)
1623
GPtrArray *ret = NULL;
1624
LU_ERROR_CHECK(error);
1625
lu_dispatch(context, groups_enumerate_full, pattern,
1626
LU_VALUE_INVALID_ID, NULL, &ret, error);
1632
lu_users_enumerate_by_group_full(struct lu_context * context,
1633
const char *pattern,
1634
struct lu_error ** error)
1636
GPtrArray *ret = NULL;
1637
LU_ERROR_CHECK(error);
1638
lu_dispatch(context, users_enumerate_by_group_full, pattern,
1639
LU_VALUE_INVALID_ID, NULL, (gpointer*) &ret, error);
1644
lu_groups_enumerate_by_user_full(struct lu_context * context,
1645
const char *pattern,
1646
struct lu_error ** error)
1648
GPtrArray *ret = NULL;
1649
LU_ERROR_CHECK(error);
1650
lu_dispatch(context, groups_enumerate_by_user_full, pattern,
1651
LU_VALUE_INVALID_ID, NULL, (gpointer*) &ret, error);
1657
lu_get_first_unused_id(struct lu_context *ctx,
1658
enum lu_entity_type type,
1662
char buf[LINE_MAX * 4];
1664
g_return_val_if_fail(ctx != NULL, (id_t)-1);
1667
if (type == lu_user) {
1668
struct passwd pwd, *err;
1669
struct lu_error *error = NULL;
1671
/* There may be read-only sources of user information
1672
* on the system, and we want to avoid allocating an ID
1673
* that's already in use by a service we can't write
1674
* to, so check with NSS first. FIXME: use growing
1676
if ((getpwuid_r(id, &pwd, buf, sizeof(buf), &err) == 0) &&
1681
if (lu_user_lookup_id(ctx, id, ent, &error)) {
1688
lu_error_free(&error);
1691
} while (id != (id_t)-1);
1692
} else if (type == lu_group) {
1693
struct group grp, *err;
1694
struct lu_error *error = NULL;
1696
/* There may be read-only sources of user information
1697
* on the system, and we want to avoid allocating an ID
1698
* that's already in use by a service we can't write
1699
* to, so check with NSS first. */
1700
getgrgid_r(id, &grp, buf, sizeof(buf), &err);
1705
if (lu_group_lookup_id(ctx, id, ent, &error)) {
1712
lu_error_free(&error);
1715
} while (id != (id_t)-1);
1724
lu_default_int(struct lu_context *context, const char *name,
1725
enum lu_entity_type type, gboolean is_system, struct lu_ent *ent)
1729
char *cfgkey, *tmp, *end;
1730
char buf[LINE_MAX * 4];
1731
const char *top, *idkey, *idkeystring, *val, *key;
1732
id_t id = DEFAULT_ID;
1733
struct group grp, *err;
1734
struct lu_error *error = NULL;
1735
gpointer macguffin = NULL;
1738
g_return_val_if_fail(context != NULL, FALSE);
1739
g_return_val_if_fail(name != NULL, FALSE);
1740
g_return_val_if_fail(strlen(name) > 0, FALSE);
1741
g_return_val_if_fail((type == lu_user) || (type == lu_group), FALSE);
1742
g_return_val_if_fail(ent != NULL, FALSE);
1743
g_return_val_if_fail(ent->magic == LU_ENT_MAGIC, FALSE);
1745
/* Clear out and initialize the record. */
1746
lu_ent_clear_all(ent);
1747
lu_ent_clear_modules(ent);
1750
/* Set the name of the user/group. */
1751
memset(&value, 0, sizeof(value));
1752
g_value_init(&value, G_TYPE_STRING);
1753
g_value_set_string(&value, name);
1754
if (ent->type == lu_user) {
1755
lu_ent_clear(ent, LU_USERNAME);
1756
lu_ent_add(ent, LU_USERNAME, &value);
1757
/* Additionally, pick a default default group. */
1758
g_value_unset(&value);
1759
/* FIXME: handle arbitrarily long lines. */
1760
if ((getgrnam_r("users", &grp, buf, sizeof(buf), &err) == 0) &&
1762
lu_value_init_set_id(&value, grp.gr_gid);
1764
g_value_init(&value, G_TYPE_LONG);
1765
g_value_set_long(&value, -1);
1767
lu_ent_clear(ent, LU_GIDNUMBER);
1768
lu_ent_add(ent, LU_GIDNUMBER, &value);
1769
} else if (ent->type == lu_group) {
1770
lu_ent_clear(ent, LU_GROUPNAME);
1771
lu_ent_add(ent, LU_GROUPNAME, &value);
1773
g_value_unset(&value);
1775
/* Figure out which part of the configuration we need to iterate over
1776
* to initialize the structure. */
1777
if (type == lu_user) {
1778
top = "userdefaults";
1779
idkey = LU_UIDNUMBER;
1780
idkeystring = G_STRINGIFY_ARG(LU_UIDNUMBER);
1782
top = "groupdefaults";
1783
idkey = LU_GIDNUMBER;
1784
idkeystring = G_STRINGIFY_ARG(LU_GIDNUMBER);
1787
/* The system flag determines where we will start searching for
1788
* unused IDs to assign to this entity. */
1792
cfgkey = g_strdup_printf("%s/%s", top, idkey);
1793
val = lu_cfg_read_single(context, cfgkey, NULL);
1796
cfgkey = g_strdup_printf("%s/%s", top, idkeystring);
1797
val = lu_cfg_read_single(context, cfgkey, NULL);
1804
imax = strtoimax(val, &tmp, 10);
1805
if (errno == 0 && *tmp == 0 && tmp != val
1806
&& (id_t)imax == imax)
1813
/* Search for a free ID. */
1814
id = lu_get_first_unused_id(context, type, id);
1816
/* Add this ID to the entity. */
1817
lu_value_init_set_id(&value, id);
1818
lu_ent_add(ent, idkey, &value);
1819
g_value_unset(&value);
1821
/* Now iterate to find the rest. */
1822
keys = lu_cfg_read_keys(context, top);
1823
for (p = keys; p && p->data; p = g_list_next(p)) {
1827
const char *realkey, *configkey;
1829
{LU_USERNAME, G_STRINGIFY_ARG(LU_USERNAME)},
1830
{LU_USERPASSWORD, G_STRINGIFY_ARG(LU_USERPASSWORD)},
1831
{LU_UIDNUMBER, G_STRINGIFY_ARG(LU_UIDNUMBER)},
1832
{LU_GIDNUMBER, G_STRINGIFY_ARG(LU_GIDNUMBER)},
1833
{LU_GECOS, G_STRINGIFY_ARG(LU_GECOS)},
1834
{LU_HOMEDIRECTORY, G_STRINGIFY_ARG(LU_HOMEDIRECTORY)},
1835
{LU_LOGINSHELL, G_STRINGIFY_ARG(LU_LOGINSHELL)},
1837
{LU_GROUPNAME, G_STRINGIFY_ARG(LU_GROUPNAME)},
1838
{LU_GROUPPASSWORD, G_STRINGIFY_ARG(LU_GROUPPASSWORD)},
1839
{LU_MEMBERNAME, G_STRINGIFY_ARG(LU_MEMBERNAME)},
1840
{LU_ADMINISTRATORNAME,
1841
G_STRINGIFY_ARG(LU_ADMINISTRATORNAME)},
1843
{LU_SHADOWNAME, G_STRINGIFY_ARG(LU_SHADOWNAME)},
1844
{LU_SHADOWPASSWORD, G_STRINGIFY_ARG(LU_SHADOWPASSWORD)},
1845
{LU_SHADOWLASTCHANGE,
1846
G_STRINGIFY_ARG(LU_SHADOWLASTCHANGE)},
1847
{LU_SHADOWMIN, G_STRINGIFY_ARG(LU_SHADOWMIN)},
1848
{LU_SHADOWMAX, G_STRINGIFY_ARG(LU_SHADOWMAX)},
1849
{LU_SHADOWWARNING, G_STRINGIFY_ARG(LU_SHADOWWARNING)},
1850
{LU_SHADOWINACTIVE, G_STRINGIFY_ARG(LU_SHADOWINACTIVE)},
1851
{LU_SHADOWEXPIRE, G_STRINGIFY_ARG(LU_SHADOWEXPIRE)},
1852
{LU_SHADOWFLAG, G_STRINGIFY_ARG(LU_SHADOWFLAG)},
1854
{LU_COMMONNAME, G_STRINGIFY_ARG(LU_COMMONNAME)},
1855
{LU_GIVENNAME, G_STRINGIFY_ARG(LU_GIVENNAME)},
1856
{LU_SN, G_STRINGIFY_ARG(LU_SN)},
1857
{LU_ROOMNUMBER, G_STRINGIFY_ARG(LU_ROOMNUMBER)},
1858
{LU_TELEPHONENUMBER,
1859
G_STRINGIFY_ARG(LU_TELEPHONENUMBER)},
1860
{LU_HOMEPHONE, G_STRINGIFY_ARG(LU_HOMEPHONE)},
1861
{LU_EMAIL, G_STRINGIFY_ARG(LU_EMAIL)},
1868
{"%d", lu_util_shadow_current_date(context->scache)},
1869
/* Must be index 2, see below! */
1870
{"%u", NULL} /* value set later */
1873
/* Possibly map the key to an internal name. */
1874
key = (const char *) p->data;
1875
for (i = 0; i < G_N_ELEMENTS(keymap); i++) {
1876
if (strcmp(key, keymap[i].configkey) == 0) {
1877
key = keymap[i].realkey;
1882
/* Skip over the key which represents the user/group ID,
1883
* because we only used it as a starting point. */
1884
if (g_ascii_strcasecmp(idkey, key) == 0) {
1888
/* Generate the key and read the value for the item. */
1889
cfgkey = g_strdup_printf("%s/%s", top, (const char *)p->data);
1890
val = lu_cfg_read_single(context, cfgkey, NULL);
1893
/* Create a copy of the value to mess with. */
1894
g_assert(val != NULL);
1895
tmp = g_strdup(val);
1897
subst[2].value = g_strdup_printf("%jd", (intmax_t)id);
1898
/* Perform substitutions. */
1899
for (i = 0; i < G_N_ELEMENTS(subst); i++) {
1900
while (strstr(tmp, subst[i].format) != NULL) {
1901
char *pre, *post, *tmp2, *where;
1903
where = strstr(tmp, subst[i].format);
1904
pre = g_strndup(tmp, where - tmp);
1905
post = g_strdup(where +
1906
strlen(subst[i].format));
1907
tmp2 = g_strconcat(pre,
1917
g_free((char *)subst[2].value);
1919
/* Check if we can represent this value as a number. */
1921
imax = strtoimax(tmp, &end, 10);
1922
if (errno == 0 && *end == 0 && end != tmp
1923
&& (long)imax == imax) {
1924
g_value_init(&value, G_TYPE_LONG);
1925
g_value_set_long(&value, imax);
1926
} else if (errno == 0 && *end == 0 && end != tmp
1927
&& (id_t)imax == imax)
1928
lu_value_init_set_id(&value, imax);
1930
g_value_init(&value, G_TYPE_STRING);
1931
g_value_set_string(&value, tmp);
1935
/* Add the transformed value. */
1936
lu_ent_clear(ent, key);
1937
lu_ent_add(ent, key, &value);
1938
g_value_unset(&value);
1944
/* Now let the modules do their thing. */
1945
lu_dispatch(context, (type == lu_user) ? user_default : group_default,
1946
name, is_system, ent, &macguffin, &error);
1947
if (error != NULL) {
1948
lu_error_free(&error);
1951
/* Make the pending set be the same as the current set. */
1958
lu_user_default(struct lu_context *context, const char *name,
1959
gboolean system_account, struct lu_ent *ent)
1961
return lu_default_int(context, name, lu_user, system_account, ent);
1965
lu_group_default(struct lu_context *context, const char *name,
1966
gboolean system_account, struct lu_ent *ent)
1968
return lu_default_int(context, name, lu_group, system_account, ent);