オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.6.x/ccs-tools/ccstools/mailauth.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1744 - (show annotations) (download) (as text)
Thu Oct 23 05:42:28 2008 UTC (15 years, 7 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 7386 byte(s)


1 /*
2 * mailauth.c
3 *
4 * An example program for CERBERUS.
5 * ( http://sourceforge.jp/projects/tomoyo/document/winf2005-en.pdf )
6 *
7 * Copyright (C) 2005-2008 NTT DATA CORPORATION
8 *
9 * Version: 1.6.5-pre 2008/10/23
10 */
11 #define _GNU_SOURCE
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <sys/time.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <termios.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <sys/wait.h>
23 #include <time.h>
24
25 static int str_starts(char *src, const char *find)
26 {
27 const int len = strlen(find);
28 if (strncmp(src, find, len))
29 return 0;
30 memmove(src, src + len, strlen(src + len) + 1);
31 return 1;
32 }
33
34 static char *str_dup(const char *str)
35 {
36 char *cp = strdup(str);
37 if (!cp) {
38 fprintf(stderr, "Out of memory\n");
39 exit(1);
40 }
41 return cp;
42 }
43
44 static void unescape_line(unsigned char *buffer)
45 {
46 unsigned char *cp = buffer;
47 unsigned char c;
48 unsigned char d;
49 unsigned char e;
50 if (!cp)
51 return;
52 while (1) {
53 c = *buffer++;
54 if (!c)
55 break;
56 if (c != '\\') {
57 *cp++ = c;
58 continue;
59 }
60 c = *buffer++;
61 if (c == '\\') {
62 *cp++ = c;
63 continue;
64 }
65 if (c < '0' || c > '3')
66 break;
67 d = *buffer++;
68 if (d < '0' || d > '7')
69 break;
70 e = *buffer++;
71 if (e < '0' || e > '7')
72 break;
73 *cp++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
74 }
75 *cp = '\0';
76 }
77
78 static void normalize_line(unsigned char *buffer)
79 {
80 unsigned char *sp = buffer;
81 unsigned char *dp = buffer;
82 int first = 1;
83 while (*sp && (*sp <= 32 || 127 <= *sp))
84 sp++;
85 while (*sp) {
86 if (!first)
87 *dp++ = ' ';
88 first = 0;
89 while (32 < *sp && *sp < 127)
90 *dp++ = *sp++;
91 while (*sp && (*sp <= 32 || 127 <= *sp))
92 sp++;
93 }
94 *dp = '\0';
95 }
96
97 #define PASSWORD_PROMPT "PASSWORD_PROMPT "
98 #define MAX_TRIALS "MAX_TRIALS "
99 #define SLEEP_ON_FAILURE "SLEEP_ON_FAILURE "
100 #define EXEC_ON_SUCCESS "EXEC_ON_SUCCESS "
101 #define MAIL_COMMAND "MAIL_COMMAND "
102 #define SINGLE_FAILURE_MESSAGE "SINGLE_FAILURE_MESSAGE "
103 #define COMPLETE_FAILURE_MESSAGE "COMPLETE_FAILURE_MESSAGE "
104
105 static char *password_prompt = "Enter\\040password";
106 static unsigned int max_trials = 3;
107 static unsigned int sleep_on_failure = 3;
108 static char *exec_on_success = "/bin/sh";
109 static char *mail_command = NULL;
110 static char *single_failure_message = "Incorrect\\040password.";
111 static char *complete_failure_message = "Authentication\\040failed.";
112
113 static void show_help(const char *argv0)
114 {
115 char *self = canonicalize_file_name(argv0);
116 fprintf(stderr,
117 "This is an interpreter for one-time-password-using-mail "
118 "authentication script. To perform "
119 "one-time-password-using-mail authentication, create a program "
120 "like the following example.\n\n");
121 printf("#! %s\n"
122 PASSWORD_PROMPT "%s\n"
123 MAX_TRIALS "%d\n"
124 SLEEP_ON_FAILURE "%d\n"
125 EXEC_ON_SUCCESS "%s\n"
126 MAIL_COMMAND "%s\n"
127 SINGLE_FAILURE_MESSAGE "%s\n"
128 COMPLETE_FAILURE_MESSAGE "%s\n",
129 self,
130 password_prompt, max_trials, sleep_on_failure, exec_on_success,
131 "curl --data-binary @- https://your.server/path_to_cgi",
132 single_failure_message, complete_failure_message);
133 fprintf(stderr,
134 "\n"
135 PASSWORD_PROMPT "is a string to display before user's input.\n"
136 MAX_TRIALS "is the maximal count the user can try.\n"
137 SLEEP_ON_FAILURE "is the delay in second for each failure.\n"
138 EXEC_ON_SUCCESS "is a program to execute when the "
139 "authentication succeeded.\n"
140 MAIL_COMMAND "is the command line to notify password.\n"
141 SINGLE_FAILURE_MESSAGE "is a string to display when "
142 "the authentication failed for once.\n"
143 COMPLETE_FAILURE_MESSAGE "is a string to display when "
144 "the authentication failed for all trials.\n"
145 "The above example sends password to "
146 "https://your.server/path_to_cgi using curl.\n"
147 "Any character with value <= 0x20 or 0x7F <= values "
148 "are regarded as a delimiter.\n"
149 "You have to follow the character representation rule shown "
150 "below.\n"
151 " ASCII character (0x21 <= value <= 0x5B or 0x5D <= value "
152 "<= 7E).\n"
153 " \\\\ for \\ character (value = 0x5C).\n"
154 " \\ooo style octal representation (value = any).\n"
155 "The line "MAIL_COMMAND "is passed to system(), so "
156 "escape appropriately as needed.\n");
157 }
158
159 static int parse_script(const char *argv1)
160 {
161 char buffer[8192];
162 FILE *fp = fopen(argv1, "r");
163 if (!fp) {
164 fprintf(stderr, "Can't open %s\n", argv1);
165 return 1;
166 }
167 while (memset(buffer, 0, sizeof(buffer)),
168 fgets(buffer, sizeof(buffer) - 1, fp)) {
169 char *cp = strchr(buffer, '\n');
170 unsigned int v;
171 if (*cp) {
172 *cp = '\0';
173 } else if (!feof(fp)) {
174 fprintf(stderr, "Line too long.\n");
175 fclose(fp);
176 return 1;
177 }
178 normalize_line(buffer);
179 if (str_starts(buffer, PASSWORD_PROMPT))
180 password_prompt = str_dup(buffer);
181 else if (sscanf(buffer, MAX_TRIALS "%u", &v) == 1)
182 max_trials = v;
183 else if (sscanf(buffer, SLEEP_ON_FAILURE "%u", &v) == 1)
184 sleep_on_failure = v;
185 else if (str_starts(buffer, EXEC_ON_SUCCESS))
186 exec_on_success = str_dup(buffer);
187 else if (str_starts(buffer, MAIL_COMMAND))
188 mail_command = str_dup(buffer);
189 else if (str_starts(buffer, SINGLE_FAILURE_MESSAGE))
190 single_failure_message = str_dup(buffer);
191 else if (str_starts(buffer, COMPLETE_FAILURE_MESSAGE))
192 complete_failure_message = str_dup(buffer);
193 }
194 fclose(fp);
195 if (!mail_command) {
196 fprintf(stderr, "No mail command found.\n");
197 return 1;
198 }
199 password_prompt = str_dup(password_prompt);
200 unescape_line(password_prompt);
201 exec_on_success = str_dup(exec_on_success);
202 unescape_line(exec_on_success);
203 single_failure_message = str_dup(single_failure_message);
204 unescape_line(single_failure_message);
205 complete_failure_message = str_dup(complete_failure_message);
206 unescape_line(complete_failure_message);
207 return 0;
208 }
209
210 static int do_auth(void)
211 {
212 char password[16];
213 char buffer[8192];
214 { /* Create password. */
215 int i = 0;
216 FILE *fp = fopen("/dev/urandom", "r");
217 if (!fp) {
218 fprintf(stderr, "Can't open /dev/urandom .\n");
219 return 1;
220 }
221 memset(password, 0, sizeof(password));
222 while (i < sizeof(password)) {
223 const unsigned int c = fgetc(fp);
224 if (c < 10)
225 password[i++] = c + '0';
226 }
227 fclose(fp);
228 }
229 { /* Send password. */
230 FILE *fp = popen(mail_command, "w");
231 if (!fp) {
232 fprintf(stderr, "Can't send mail\n");
233 return 1;
234 }
235 fprintf(fp, "%s\n", password);
236 pclose(fp);
237 }
238 /* fprintf(stderr, "%s\n", password); */
239 { /* Check password. */
240 int trial;
241 for (trial = 0; trial < max_trials; trial++) {
242 char *cp;
243 printf("%s\n", password_prompt);
244 memset(buffer, 0, sizeof(buffer));
245 fgets(buffer, sizeof(buffer) - 1, stdin);
246 cp = strchr(buffer, '\n');
247 if (cp)
248 *cp = '\0';
249 if (!strcmp(buffer, password)) {
250 execlp(exec_on_success, exec_on_success, NULL);
251 fprintf(stderr, "Can't execute %s\n",
252 exec_on_success);
253 exit(1);
254 }
255 printf("%s\n", single_failure_message);
256 sleep(sleep_on_failure);
257 }
258 }
259 printf("%s\n", complete_failure_message);
260 return 1;
261 }
262
263 int main(int argc, char *argv[])
264 {
265 unsetenv("SHELLOPTS"); /* Make sure popen() executes MAIL_COMMAND */
266 if (argc != 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")) {
267 show_help(argv[0]);
268 return 1;
269 }
270 if (parse_script(argv[1]))
271 return 1;
272 return do_auth();
273 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26