Annotation of embedtools/src/cfexec.c, revision 1.1.1.1.2.4
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.4! misho 6: * $Id: cfexec.c,v 1.1.1.1.2.3 2009/11/12 11:51:50 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);
1.1.1.1.2.3 misho 113: Timeout = strtonum(szUser, 0, 3600, &err);
114: if (!Timeout && err) {
1.1 misho 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':
1.1.1.1.2.3 misho 152: Timeout = strtonum(optarg, 0, 3600, &err);
153: if (!Timeout && err) {
1.1 misho 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:
1.1.1.1.2.3 misho 194: if (Timeout) {
195: memset(&ts, 0, sizeof ts);
196: ts.tv_sec = Timeout;
197: }
1.1.1.1.2.2 misho 198: switch (kevent(kq, &chg, 1, &evt, 1, !Timeout ? NULL : &ts)) {
1.1 misho 199: case -1:
200: printf("Error:: can`t execute safe mount #%d - %s\n",
201: errno, strerror(errno));
202: stat = 7;
203: break;
204: case 0:
205: VERB(1) printf("Timeout reached - secure mount\n");
206: default:
207: VERB(1) printf("Lock file is deleted - secure mount\n");
208: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
209: stat = 8;
210: }
211:
212: close(kq);
213: close(f);
214: unlink(szSess);
215: break;
216: }
217: } else {
218: /*
219: sigemptyset(&sig);
220: sigaddset(&sig, SIGINT);
221: sigaddset(&sig, SIGTSTP);
222: sigprocmask(SIG_BLOCK, &sig, &oldsig);
223: */
224:
225: if (update(MNT_UPDATE) == -1)
226: return 4;
227:
228: switch ((pid = vfork())) {
229: case -1:
230: printf("Error:: can`t execute safe mount #%d - %s\n",
231: errno, strerror(errno));
232: return 5;
233: case 0:
234: VERB(5) printf("Go to running process %s\n", *argv);
235: if (chroot(szChroot) == -1) {
236: printf("Error:: can`t chroot to dir %s #%d - %s\n",
237: szChroot, errno, strerror(errno));
238: } else {
239: if (strncmp(szUser, "root", 5))
240: setuser();
241:
1.1.1.1.2.4! misho 242: /* chdir("/"); */
1.1 misho 243: execvp(*argv, argv);
244: }
245: _exit(127);
246: break;
247: default:
248: waitpid(pid, &stat, 0);
249: VERB(3) printf("Return code: %d\n", stat);
250: if (stat == 32512)
251: stat = 127;
252:
253: if (update(MNT_UPDATE | MNT_RDONLY) == -1)
254: return 8;
255: }
256:
257: // sigprocmask(SIG_SETMASK, &oldsig, NULL);
258: }
259:
260: return stat;
261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>