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 565 by douglas, 2005-08-28T03:37:15-07:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines