Annotation of embedtools/src/cfexec.c, revision 1.1.1.1.2.2
1.1 misho 1: /*************************************************************************
2: * (C) 2009 AITNET - Sofia/Bulgaria - <office@aitbg.com>
3: * by Michael Pounov <misho@aitbg.com>
4: *
5: * $Author: misho $
1.1.1.1.2.2! misho 6: * $Id: cfexec.c,v 1.1.1.1.2.1 2009/11/12 10:41:47 misho Exp $
1.1 misho 7: *
8: *************************************************************************/
9: #include "global.h"
10:
11:
12: sl_config cfg;
13: int Verbose, Timeout, kq;
14: char szUser[MAX_STR], szMount[MAXPATHLEN], szDev[MAXPATHLEN],
15: szChroot[MAXPATHLEN], szSess[MAXPATHLEN], szConfig[MAXPATHLEN];
16: extern char compiled[], compiledby[], compilehost[];
17:
1.1.1.1.2.1 misho 18:
1.1 misho 19: static void Usage()
20: {
21:
22: printf( "CFExec is tool for managment R/W operation with CompactFlash\n"
23: "=== %s === %s@%s ===\n\n"
24: " Syntax: cfexec [options] [exec_file]\n\n"
25: "\t-v\t\tVerbose ...\n"
26: "\t-c <dir>\tAfter execute chroot to dir [default=/]\n"
27: "\t-u <user>\tAfter execute suid to user [default=root]\n"
28: "\t-d <dev>\tOther device [default=/dev/ufs/AITBSDonCF]\n"
29: "\t-m <mnt>\tOther mount dir [default=/cf]\n"
30: "\t-t <sec>\tTimeout for autolock mount dir after seconds [default=300]\n"
31: "\n", compiled, compiledby, compilehost);
32: }
33:
34: static int update(int flags)
35: {
36: struct ufs_args mnt;
37:
38: memset(&mnt, 0, sizeof mnt);
39: mnt.fspec = szDev;
40: if (mount("ufs", szMount, flags, &mnt) == -1) {
41: printf("Error:: can`t update mount %s #%d - %s\n", szMount, errno, strerror(errno));
42: return -1;
43: }
44:
45: VERB(5) printf("Info(5):: safe mount for device %s to %s operation (%s)\n",
46: szDev, szMount, (flags & MNT_RDONLY) ? "ro" : "rw");
47: return 0;
48: }
49:
50: static void setuser()
51: {
52: struct passwd *pw;
53:
54: pw = getpwnam(szUser);
55: if (pw) {
56: setuid(pw->pw_uid);
57: setgid(pw->pw_gid);
58: endpwent();
59:
60: VERB(5) printf("Info(5):: Suid to user %s.\n", szUser);
61: } else
62: VERB(5) printf("Info(5):: Can`t suid to user %s !\n", szUser);
63: }
64:
65: static int mkevent(struct kevent *chg, struct kevent *evt)
66: {
67: int f;
68: char szStr[MAX_STR];
69:
70: f = open(szSess, O_CREAT | O_WRONLY | O_TRUNC, 0644);
71: if (f == -1) {
72: printf("Error:: can`t lock session #%d - %s\n", errno, strerror(errno));
73: return -1;
74: } else {
75: memset(szStr, 0, MAX_STR);
76: snprintf(szStr, MAX_STR, "%d", getpid());
77: write(f, szStr, strlen(szStr));
78: }
79: VERB(3) printf("Created lock file %s\n", szSess);
80:
81: kq = kqueue();
82: if (kq == -1) {
83: printf("Error:: can`t execute safe mount #%d - %s\n", errno, strerror(errno));
84: close(f);
85: unlink(szSess);
86: return -1;
87: } else {
88: memset(chg, 0, sizeof(struct kevent));
89: memset(evt, 0, sizeof(struct kevent));
90:
91: EV_SET(chg, f, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME | NOTE_REVOKE, 0, NULL);
92: }
93:
94: return f;
95: }
96:
97: // ---------------------------------
98:
99: int main(int argc, char **argv)
100: {
101: char ch;
102: const char *err;
103: struct kevent chg, evt;
104: struct timespec ts;
105: pid_t pid;
106: int f, stat = 0;
107: // sigset_t sig, oldsig;
108:
109: strlcpy(szConfig, DEFAULT_CONFIG, MAXPATHLEN);
110: // Load variables from config if exists
111: if (!LoadConfig(szConfig, &cfg)) {
112: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("timeout"), CFG(szUser), MAX_STR, DEFAULT_TIMEOUT);
113: Timeout = strtonum(szUser, 1, 3600, &err);
114: if (!Timeout) {
115: printf("Error:: in seconds for timeout %s - %s\n", optarg, err);
116: UnloadConfig(&cfg);
117: return 1;
118: }
119: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("suid"), CFG(szUser), MAX_STR, DEFAULT_USER);
120: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("mount"), CFG(szMount), MAXPATHLEN, DEFAULT_MOUNT);
121: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("device"), CFG(szDev), MAXPATHLEN, DEFAULT_DEVICE);
122: cfg_LoadAttribute(&cfg, CFG("cfexec"), CFG("chroot"), CFG(szChroot), MAXPATHLEN, DEFAULT_CHROOT);
123:
124: UnloadConfig(&cfg);
125: } else {
126: Timeout = atoi(DEFAULT_TIMEOUT);
127: strlcpy(szUser, DEFAULT_USER, MAX_STR);
128: strlcpy(szMount, DEFAULT_MOUNT, MAXPATHLEN);
129: strlcpy(szDev, DEFAULT_DEVICE, MAXPATHLEN);
130: strlcpy(szChroot, DEFAULT_CHROOT, MAXPATHLEN);
131: }
132:
133: // Load variables from arguments if exists
134: while ((ch = getopt(argc, argv, "hvu:c:d:m:t:")) != -1)
135: switch (ch) {
136: case 'v':
137: Verbose++;
138: break;
139: case 'u':
140: strlcpy(szUser, optarg, MAX_STR);
141: break;
142: case 'c':
143: strlcpy(szChroot, optarg, MAXPATHLEN);
144: break;
145: case 'd':
146: strlcpy(szDev, optarg, MAXPATHLEN);
147: break;
148: case 'm':
149: strlcpy(szMount, optarg, MAXPATHLEN);
150: break;
151: case 't':
152: Timeout = strtonum(optarg, 1, 3600, &err);
153: if (!Timeout) {
154: printf("Error:: in seconds for timeout %s - %s\n",
155: optarg, err);
156: return 1;
157: }
158: break;
159: case 'h':
160: default:
161: Usage();
162: return 1;
163: }
164: argc -= optind;
165: argv += optind;
166:
167: memset(szSess, 0, MAXPATHLEN);
168: snprintf(szSess, MAXPATHLEN, "%s%s-cfexec.LCK", DEFAULT_TMP, szMount);
169:
170: VERB(3) printf("Info(3):: Chroot=%s SUID=%s Device=%s Mount=%s Timeout=%d Session=%s\n",
171: szChroot, szUser, szDev, szMount, Timeout, szSess);
172:
173: if (!access(szSess, F_OK)) {
174: printf("cfexec already running ...\n");
175: return 127;
176: }
177:
178: if (!argc) {
179: switch (fork()) {
180: case -1:
181: printf("Error:: can`t execute safe mount #%d - %s\n",
182: errno, strerror(errno));
183: return 3;
184: case 0:
185: VERB(5) printf("Info(5):: Go safe mount.\n");
186: setsid();
187:
188: if (update(MNT_UPDATE) == -1)
189: return 4;
190:
191: if ((f = mkevent(&chg, &evt)) == -1)
192: return 5;
193:
194: memset(&ts, 0, sizeof ts);
195: ts.tv_sec = Timeout;
1.1.1.1.2.2! misho 196: switch (kevent(kq, &chg, 1, &evt, 1, !Timeout ? NULL : &ts)) {
1.1 misho 197: case -1:
198: printf("Error:: can`t execute safe mount #%d - %s\n",
199: errno, strerror(errno));
200: stat = 7;
201: break;
202: case 0:
203: VERB(1) printf("Timeout reached - secure mount\n");
204: default:
205: VERB(1) printf("Lock file is deleted - secure mount\n");
206: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
207: stat = 8;
208: }
209:
210: close(kq);
211: close(f);
212: unlink(szSess);
213: break;
214: }
215: } else {
216: /*
217: sigemptyset(&sig);
218: sigaddset(&sig, SIGINT);
219: sigaddset(&sig, SIGTSTP);
220: sigprocmask(SIG_BLOCK, &sig, &oldsig);
221: */
222:
223: if (update(MNT_UPDATE) == -1)
224: return 4;
225:
226: switch ((pid = vfork())) {
227: case -1:
228: printf("Error:: can`t execute safe mount #%d - %s\n",
229: errno, strerror(errno));
230: return 5;
231: case 0:
232: VERB(5) printf("Go to running process %s\n", *argv);
233: if (chroot(szChroot) == -1) {
234: printf("Error:: can`t chroot to dir %s #%d - %s\n",
235: szChroot, errno, strerror(errno));
236: } else {
237: if (strncmp(szUser, "root", 5))
238: setuser();
239:
240: chdir("/");
241: execvp(*argv, argv);
242: }
243: _exit(127);
244: break;
245: default:
246: waitpid(pid, &stat, 0);
247: VERB(3) printf("Return code: %d\n", stat);
248: if (stat == 32512)
249: stat = 127;
250:
251: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
252: return 8;
253: }
254:
255: // sigprocmask(SIG_SETMASK, &oldsig, NULL);
256: }
257:
258: return stat;
259: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>