Log Kerberos errors consistently
[public/pyceo-broken.git] / src / addclub.c
1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <ctype.h>
8 #include <pwd.h>
9 #include <grp.h>
10 #include <errno.h>
11 #include <libgen.h>
12 #include <syslog.h>
13
14 #include "util.h"
15 #include "common.h"
16 #include "config.h"
17 #include "ldap.h"
18 #include "krb5.h"
19 #include "kadm.h"
20 #include "addhomedir.h"
21
22 char *prog = NULL;
23 char *user = NULL;
24 int privileged = 0;
25
26 static int force = 0;
27 static int no_notify = 0;
28
29 static char *name = NULL;
30 static char *userid = NULL;
31
32 static struct option opts[] = {
33     { "force", 0, NULL, 'f' },
34     { "no-notify", 0, NULL, 'q' },
35     { NULL, 0, NULL, '\0' },
36 };
37
38 static void usage() {
39     fprintf(stderr, "Usage: %s userid clubname\n", prog);
40     exit(2);
41 }
42
43 int addclub() {
44     int krb_ok, user_ok, group_ok, sudo_ok, home_ok;
45     int id;
46     char homedir[1024];
47     char acl_s[1024] = {0};
48
49     notice("adding uid=%s cn=%s by %s", userid, name, user);
50
51     if (setreuid(0, 0))
52         fatalpe("setreuid");
53     if (setregid(0, 0))
54         fatalpe("setregid");
55
56     if (!force && getpwnam(userid) != NULL)
57         deny("user %s already exists", userid);
58
59     snprintf(homedir, sizeof(homedir), "%s/%s", club_home, userid);
60     ceo_krb5_init();
61     ceo_ldap_init();
62     ceo_kadm_init();
63
64     if (ceo_user_exists(userid))
65         deny("user %s already exists in LDAP", userid);
66     if (ceo_group_exists(userid))
67         deny("group %s already exists in LDAP", userid);
68
69     if ((id = ceo_new_uid(club_min_id, club_max_id)) <= 0)
70         fatal("no available uids in range [%d, %d]", club_min_id, club_max_id);
71
72     snprintf(acl_s, sizeof(acl_s), club_home_acl, userid);
73
74     krb_ok = ceo_del_princ(userid);
75     if (!krb_ok)
76         notice("successfully cleared principal for %s", userid);
77
78     user_ok = krb_ok || ceo_add_user(userid, users_base, "club", name, homedir,
79             club_shell, id, NULL);
80     if (!user_ok)
81         notice("successfully created account for %s", userid);
82
83     group_ok = user_ok || ceo_add_group(userid, groups_base, id);
84     if (!group_ok)
85         notice("successfully created group for %s", userid);
86
87     sudo_ok = user_ok || ceo_add_group_sudo(userid, sudo_base);
88     if (!sudo_ok)
89         notice("successfully added group sudo entry for %s", userid);
90
91     home_ok = user_ok || ceo_create_home(homedir, refquota, id, id, homedir_mode, acl_s);
92     if (!home_ok)
93         notice("successfully created home directory for %s", userid);
94
95     notice("done uid=%s", userid);
96
97     if (!no_notify && !user_ok) {
98         int pid;
99         int hkp[2];
100         FILE *hkf;
101         int status;
102
103         if (pipe(hkp))
104             errorpe("pipe");
105
106         fflush(stdout);
107         fflush(stderr);
108
109         pid = fork();
110
111         if (!pid) {
112             fclose(stdout);
113             fclose(stderr);
114             close(hkp[1]);
115             dup2(hkp[0], 0);
116             exit(execl(notify_hook, notify_hook, prog, user, userid, name, NULL));
117         }
118
119         hkf = fdopen(hkp[1], "w");
120
121         if (group_ok)
122             fprintf(hkf, "failed to create group\n");
123         if (home_ok)
124             fprintf(hkf, "failed to create home directory\n");
125         if (!group_ok && !home_ok)
126             fprintf(hkf, "all failures went undetected\n");
127
128         fclose(hkf);
129
130         waitpid(pid, &status, 0);
131
132         if (WIFEXITED(status) && WEXITSTATUS(status))
133             notice("hook %s exited with status %d", notify_hook, WEXITSTATUS(status));
134         else if (WIFSIGNALED(status))
135             notice("hook %s killed by signal %d", notify_hook, WTERMSIG(status));
136     }
137
138     ceo_kadm_cleanup();
139     ceo_ldap_cleanup();
140     ceo_krb5_cleanup();
141
142     return krb_ok || user_ok || group_ok || home_ok;
143 }
144
145 int main(int argc, char *argv[]) {
146     int opt;
147
148     prog = basename(argv[0]);
149     init_log(prog, LOG_PID, LOG_AUTHPRIV);
150
151     configure();
152
153     user = ceo_get_user();
154     privileged = ceo_get_privileged();
155
156     while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
157         switch (opt) {
158             case 'f':
159                 if (!privileged)
160                     deny("not privileged enough to force");
161                 force = 1;
162                 break;
163             case 'q':
164                 if (!privileged)
165                     deny("not privileged enough to suppress notifications");
166                 no_notify = 1;
167                 break;
168             case '?':
169                 usage();
170                 break;
171             default:
172                 fatal("error parsing arguments");
173         }
174     }
175
176     if (argc - optind != 2)
177         usage();
178
179     userid = argv[optind++];
180     name = argv[optind++];
181
182     return addclub();
183 }