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 563 by douglas, 2005-08-28T01:55:06-07:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines