ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSAdmin/adduser.c
Revision: 807
Committed: 2006-06-29T07:39:29-07:00 (18 years, 11 months ago) by douglas
Content type: text/x-c
File size: 6098 byte(s)
Log Message:
Yarg!

File Contents

# User Rev Content
1 douglas 562 // Douglas Thrift
2     //
3     // CCS Computer Science
4     //
5     // Add User
6    
7 douglas 807 #include "common.h"
8 douglas 572
9 douglas 566 #include <errno.h>
10 douglas 807 #include <stdbool.h>
11 douglas 562 #include <sys/resource.h>
12     #include <sys/time.h>
13     #include <sys/types.h>
14 douglas 566 #include <sys/stat.h>
15     #include <fcntl.h>
16 douglas 584
17 douglas 806 #ifdef _Master_
18 douglas 566 #include <fts.h>
19 douglas 807
20     static int compare(const char **key, const char **item)
21     {
22     return strcmp(*key, *item);
23     }
24    
25     static bool exists(const char *program, const char *user, jmp_buf environment)
26     {
27     int pipe_[2];
28    
29     check(pipe(pipe_), environment);
30    
31     pid_t ldapsearch;
32    
33     if (!(ldapsearch = check(fork(), environment)))
34     {
35     check(dup2(pipe_[1], 1), environment);
36     check(close(pipe_[0]), environment);
37    
38     char uid[strlen(user) + 5];
39    
40     sprintf(uid, "uid=%s", user);
41     check(execl(LDAPSEARCH, program, "-b", "ou=People,dc=ccs,dc=ucsb,dc=edu", "-H", "ldaps://" MASTER, "-LLL", "-x", uid, "1.1", NULL), environment);
42     }
43    
44     check(close(pipe_[1]), environment);
45    
46     FILE *ldapsearch_ = fdopen(pipe_[0], "r");
47     size_t size;
48     char *uid = fcheck(fgetln(ldapsearch_, &size), ldapsearch_, environment);
49     int status;
50    
51     check(waitpid(ldapsearch, &status, 0), environment);
52    
53     char user_[strlen(user) + 41];
54    
55     sprintf(user_, "dn: uid=%s,ou=People,dc=ccs,dc=ucsb,dc=edu", user);
56    
57     if (size != 0 && !strncmp(user_, uid, size - 1))
58     return true;
59    
60     static const char *users[] = {
61     # include "users.h"
62     };
63    
64     if (bsearch(&user, users, sizeof (users) / sizeof (*users), sizeof (*users), (int (*)(const void *, const void *))compare))
65     return true;
66    
67     return false;
68     }
69 douglas 584 #endif
70 douglas 562
71     int main(int argc, char *argv[])
72     {
73 douglas 564 if (argc < 1)
74     return 1;
75 douglas 567
76     umask(S_IWGRP | S_IWOTH);
77 douglas 564
78 douglas 562 int exception;
79     jmp_buf environment;
80    
81     switch (exception = setjmp(environment))
82     {
83     case 0:
84     break;
85     case 1:
86     perror(argv[0]);
87    
88     return 1;
89     default:
90     fprintf(stderr, "%s: %s\n", argv[0], (char *)exception);
91    
92     return 1;
93     }
94    
95 douglas 806 #ifdef _Master_
96 douglas 562 regex_t user_, name_;
97    
98     regcheck(regcomp(&user_, "^-user=([a-z0-9]{1,16})$", REG_EXTENDED), &user_, environment);
99     regcheck(regcomp(&name_, "^-name=([^:]+)$", REG_EXTENDED), &name_, environment);
100    
101     char user[MAXLOGNAME] = "", *name = NULL;
102 douglas 564
103 douglas 562 for (int index = 1; index != argc; ++index)
104     {
105     regmatch_t match[2];
106    
107     if (!regcheck(regexec(&user_, argv[index], 2, match, 0), &user_, environment))
108     strlcpy(user, argv[index] + match[1].rm_so, match[1].rm_eo - match[1].rm_so + 1);
109     else if (!regcheck(regexec(&name_, argv[index], 2, match, 0), &name_, environment))
110     name = argv[index] + match[1].rm_so;
111     else
112     {
113     printf("Usage: %s [-user=user] [-name=name]\n", argv[0]);
114    
115     return 1;
116     }
117     }
118    
119     regfree(&user_);
120     regfree(&name_);
121     authenticate(argv[0], environment);
122    
123     if (!strlen(user))
124     {
125     regcheck(regcomp(&user_, "^[a-z0-9]{1,16}$", REG_EXTENDED), &user_, environment);
126    
127     do
128     {
129     printf("User Name: ");
130    
131     size_t size;
132     char *user_ = fcheck(fgetln(stdin, &size), stdin, environment);
133    
134     strlcpy(user, user_, size < sizeof (user) ? size : sizeof (user));
135     }
136 douglas 807 while (regcheck(regexec(&user_, user, 0, NULL, 0), &user_, environment) || (exists(argv[0], user, environment) && fprintf(stderr, "%s: User exists\n", argv[0])));
137 douglas 562
138     regfree(&user_);
139     }
140 douglas 807 else if (exists(argv[0], user, environment))
141     longjmp(environment, (int)"User exists");
142 douglas 562
143     if (!name)
144     {
145     regcheck(regcomp(&name_, "^[^:]+$", REG_EXTENDED), &name_, environment);
146 douglas 563 get("Full Name", &name_, &name, environment);
147 douglas 562 regfree(&name_);
148     }
149    
150     char password[_PASSWORD_LEN];
151    
152     getpassword(password, environment);
153     check(setuid(geteuid()), environment);
154    
155     char slappasswd[] = "/tmp/slappasswd.XXXXXX";
156    
157     putpassword(password, slappasswd, environment);
158    
159     int pipe_[2];
160    
161     check(pipe(pipe_), environment);
162    
163 douglas 691 pid_t bash_;
164 douglas 562
165 douglas 691 if (!(bash_ = check(fork(), environment)))
166 douglas 562 {
167     check(dup2(pipe_[0], 0), environment);
168     check(close(pipe_[1]), environment);
169     check(setenv("USER", user, 1), environment);
170     check(setenv("NAME", name, 1), environment);
171     check(setenv("FILE", slappasswd, 1), environment);
172 douglas 583 setshells(shells + bash, environment);
173 douglas 562 check(execl("/ccs/bin/adduser.sh", argv[0], NULL), environment);
174     }
175    
176     check(close(pipe_[0]), environment);
177    
178     FILE *smbpasswd = fdopen(pipe_[1], "w");
179    
180     if (fprintf(smbpasswd, "%s\n%s\n", password, password) < 0)
181     longjmp(environment, 1);
182    
183     if (fclose(smbpasswd))
184     longjmp(environment, 1);
185    
186     int status;
187    
188 douglas 691 check(waitpid(bash_, &status, 0), environment);
189 douglas 562 check(unlink(slappasswd), environment);
190    
191     if (WEXITSTATUS(status))
192     return 1;
193    
194     struct passwd *entry = getpwnam(user);
195    
196     if (!entry)
197     longjmp(environment, 1);
198    
199 douglas 567 check(mkdir(entry->pw_dir, S_IRWXU | S_IRWXG | S_IRWXO), environment);
200 douglas 562 check(chown(entry->pw_dir, entry->pw_uid, entry->pw_gid), environment);
201 douglas 566 check(chdir(entry->pw_dir), environment);
202    
203 douglas 579 FTS *traversal = fts_open((char *[]){ "/usr/share/skel", "/ccs/skel", NULL }, FTS_LOGICAL | FTS_NOCHDIR, NULL);
204 douglas 566
205     if (!traversal)
206     longjmp(environment, 1);
207    
208     FTSENT *entity;
209    
210     while ((entity = fts_read(traversal)))
211     switch (entity->fts_info)
212     {
213     case FTS_D:
214     if (entity->fts_level != FTS_ROOTLEVEL)
215     {
216     check(mkdir(entity->fts_name, entity->fts_statp->st_mode), environment);
217     check(chown(entity->fts_name, entry->pw_uid, entry->pw_gid), environment);
218     check(chdir(entity->fts_name), environment);
219     }
220    
221     break;
222     case FTS_DP:
223     if (entity->fts_level != FTS_ROOTLEVEL)
224     check(chdir(".."), environment);
225    
226     break;
227     case FTS_F:
228     {
229     int output = check(open(strncmp(entity->fts_name, "dot", 3) ? entity->fts_name : entity->fts_name + 3, O_WRONLY | O_CREAT | O_EXCL, entity->fts_statp->st_mode), environment), input = check(open(entity->fts_accpath, O_RDONLY), environment);
230     char buffer[entity->fts_statp->st_blksize];
231     size_t size;
232    
233     while ((size = check(read(input, buffer, sizeof (buffer)), environment)))
234     check(write(output, buffer, size), environment);
235    
236     check(fchown(output, entry->pw_uid, entry->pw_gid), environment);
237     check(close(output), environment);
238     check(close(input), environment);
239     }
240    
241     break;
242     }
243    
244     if (errno)
245     longjmp(environment, 1);
246    
247     if (fts_close(traversal))
248     longjmp(environment, 1);
249 douglas 562 #else
250 douglas 806 longjmp(environment, (int)"Log in to " MASTER " to add users");
251 douglas 562 #endif
252    
253     return 0;
254     }