ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSAdmin/chsh.c
(Generate patch)

Comparing CCSAdmin/chsh.c (file contents):
Revision 562 by douglas, 2005-08-27T21:46:39-07:00 vs.
Revision 567 by douglas, 2005-08-28T22:42:38-07:00

# Line 10 | Line 10
10  
11   int main(int argc, char *argv[])
12   {
13 +        if (argc < 1)
14 +                return 1;
15 +
16 +        umask(S_IWGRP | S_IWOTH);
17 +        
18          int exception;
19          jmp_buf environment;
20  
# Line 27 | Line 32 | int main(int argc, char *argv[])
32                  return 1;
33          }
34  
35 +        char user[MAXLOGNAME] = "", *shell = NULL;
36 +        regex_t shell_;
37 +
38          typedef struct
39          {
40                  const char *name;
41                  char *freebsd, *linux, *darwin;
42          }
43 <        Shell;
43 >        Shells;
44  
45 <        typedef enum { sh, csh, tcsh, bash, ksh, zsh, _3sh, custom } Shells;
45 >        typedef enum { sh, csh, tcsh, bash, ksh, zsh, _3sh, custom } Shell;
46  
47 <        Shell shells[] = {
47 >        Shells shells[] = {
48                  { "sh", "/bin/sh", "/bin/sh", "/bin/sh" },
49                  { "csh", "/bin/csh", "/bin/csh", "/bin/csh" },
50                  { "tcsh", "/bin/tcsh", "/bin/tcsh", "/bin/tcsh" },
# Line 47 | Line 55 | int main(int argc, char *argv[])
55                  { "custom", NULL, NULL, NULL }
56          };
57  
58 <        for (Shells shell = sh; shell != custom; ++shell)
59 <                printf("%s, ", shells[shell].name);
58 >        char *shell_regex = NULL;
59 >
60 >        {
61 >                size_t size = 0;
62 >
63 >                for (Shell shell = sh; shell <= custom; ++shell)
64 >                {
65 >                        shell_regex = shell_regex ? realloc(shell_regex, size += strlen(shells[shell].name) + (shell != custom ? 1 : 0)) : calloc(size += strlen(shells[shell].name) + 2, 1);
66 >                        strlcat(shell_regex, shells[shell].name, size);
67 >
68 >                        if (shell != custom)
69 >                                strlcat(shell_regex, "|", size);
70 >                }
71 >        }
72 >
73 >        char shell_regex_[strlen(shell_regex) + 12];
74 >
75 >        sprintf(shell_regex_, "^-shell=(%s)$", shell_regex);
76 >        regcheck(regcomp(&shell_, shell_regex_, REG_EXTENDED), &shell_, environment);
77 >
78 >        if (!getuid())
79 >        {
80 >                regex_t user_;
81 >
82 >                regcheck(regcomp(&user_, "^-user=([a-z0-9]{1,16})$", REG_EXTENDED), &user_, environment);
83 >
84 >                for (int index = 1; index != argc; ++index)
85 >                {
86 >                        regmatch_t match[2];
87 >
88 >                        if (!regcheck(regexec(&user_, argv[index], 2, match, 0), &user_, environment))
89 >                                strlcpy(user, argv[index] + match[1].rm_so, match[1].rm_eo - match[1].rm_so + 1);
90 >                        else if (!regcheck(regexec(&shell_, argv[index], 2, match, 0), &shell_, environment))
91 >                                shell = argv[index] + match[1].rm_so;
92 >                        else
93 >                        {
94 >                                printf("Usage: %s -user=user [-shell=%s]\n", argv[0], shell_regex);
95 >
96 >                                return 1;
97 >                        }
98 >                }
99 >
100 >                regfree(&user_);
101 >
102 >                if (strlen(user))
103 >                        goto on;
104 >                else
105 >                        longjmp(environment, (int)"Cannot change root shell");
106 >        }
107 >        else
108 >                for (int index = 1; index != argc; ++index)
109 >                {
110 >                        regmatch_t match[2];
111 >
112 >                        if (!regcheck(regexec(&shell_, argv[index], 2, match, 0), &shell_, environment))
113 >                                shell = argv[index] + match[1].rm_so;
114 >                        else
115 >                        {
116 >                                printf("Usage: %s [-shell=%s]\n", argv[0], shell_regex);
117 >
118 >                                return 1;
119 >                        }
120 >                }
121 >
122 >        struct passwd *entry = getpwuid(getuid());
123 >
124 >        if (!entry)
125 >                longjmp(environment, 1);
126 >
127 >        strlcpy(user, entry->pw_name, sizeof (user));
128 > on:     regfree(&shell_);
129 >        authenticate(argv[0], environment);
130 >
131 >        if (!shell)
132 >        {
133 >                sprintf(shell_regex_, "^%s$", shell_regex);
134 >                regcheck(regcomp(&shell_, shell_regex_, REG_EXTENDED), &shell_, environment);
135 >                do
136 >                {
137 >                        printf("Shell (");
138 >
139 >                        for (Shell shell = sh; shell <= custom; ++shell)
140 >                                printf(shell != custom ? "%s, " : "%s): ", shells[shell].name);
141 >
142 >                        size_t size;
143 >                        char *shell_ = fcheck(fgetln(stdin, &size), stdin, environment);
144 >
145 >                        shell = shell ? realloc(shell, size) : malloc(size);
146 >
147 >                        strlcpy(shell, shell_, size);
148 >                }
149 >                while (regcheck(regexec(&shell_, shell, 0, NULL, 0), &shell_, environment));
150 >
151 >                regfree(&shell_);
152 >        }
153 >
154 >        free(shell_regex);
155 >
156 >        Shells *shells_ = shells + custom;
157 >
158 >        for (Shell shell_ = sh; shell_ != custom; ++shell_)
159 >                if (!strcmp(shell, shells[shell_].name))
160 >                {
161 >                        shells_ = shells + shell_;
162 >
163 >                        goto no;
164 >                }
165 >
166 >        regex_t path;
167 >
168 >        regcheck(regcomp(&path, "^/.*[^/]$", REG_EXTENDED), &path, environment);
169 >        get("FreeBSD", &path, &shells_->freebsd, environment);
170 >        get("Linux", &path, &shells_->linux, environment);
171 >        get("Darwin", &path, &shells_->darwin, environment);
172 >        regfree(&path);
173 >
174 > no:     check(setuid(geteuid()), environment);
175 >
176 >        int pipe_[2];
177 >
178 >        check(pipe(pipe_), environment);
179 >
180 >        pid_t bash_;
181  
182 <        printf("%s\n", shells[custom].name);
182 >        if (!(bash_ = check(fork(), environment)))
183 >        {
184 >                check(dup2(pipe_[0], 0), environment);
185 >                check(close(pipe_[1]), environment);
186 >                check(setenv("USER", user, 1), environment);
187 >                check(execl("/ccs/bin/chsh.sh", argv[0], NULL), environment);
188 >        }
189 >
190 >        check(close(pipe_[0]), environment);
191 >
192 >        FILE *sed = fdopen(pipe_[1], "w");
193 >
194 >        if (fprintf(sed, "%s\n%s\n%s\n", shells_->freebsd, shells_->linux, shells_->darwin) < 0)
195 >                longjmp(environment, 1);
196 >
197 >        if (fclose(sed))
198 >                longjmp(environment, 1);
199 >
200 >        int status;
201 >
202 >        check(waitpid(bash_, &status, 0), environment);
203 >
204 >        if (WEXITSTATUS(status))
205 >                return 1;
206  
207          return 0;
208   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines