ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSAdmin/adduser.c
Revision: 691
Committed: 2006-03-07T16:38:32-08:00 (19 years, 3 months ago) by douglas
Content type: text/x-c
File size: 4723 byte(s)
Log Message:
Fixed bug where adduser was setting the default shell to sh instead of bash.

File Contents

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