Subversion Repositories public

Rev

Rev 55 | Rev 63 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 55 Rev 61
Line 101... Line 101...
101
}
101
}
102
102
103
/// Program arguments
103
/// Program arguments
104
static struct argp argp = { options, parse_opt, args_doc, doc };
104
static struct argp argp = { options, parse_opt, args_doc, doc };
105
105
106
/// Unlink a file with temporarily changed UID.
-
 
107
/**
-
 
108
 * \param[in] file file to unlink
-
 
109
 * \param[in] uid UID for unlink processing
-
 
110
 *
-
 
111
 * \attention No error checking is done!
-
 
112
 */
-
 
113
void unlink_suid(const char* file, uid_t uid)
-
 
114
{
106
115
  uid_t iu = geteuid();
-
 
116
  seteuid(uid);
-
 
117
  if (unlink(file) != 0)
-
 
118
    perror("cannot remove temporary file");
-
 
119
  seteuid(iu);
-
 
120
}
-
 
121
107
122
/// Copies a file to an user table.
108
/// Copies a file to an user table.
123
/**
109
/**
124
 * \param[in] path path to file
110
 * \param[in] path path to file
125
 * \param[in] user user name
111
 * \param[in] user user name
Line 205... Line 191...
205
  struct passwd* ppwd = getpwnam(user);
191
  struct passwd* ppwd = getpwnam(user);
206
  if (ppwd == NULL) {
192
  if (ppwd == NULL) {
207
    fprintf(stderr, "cannot find user %s: %s\n", user, strerror(errno));
193
    fprintf(stderr, "cannot find user %s: %s\n", user, strerror(errno));
208
    return false;
194
    return false;
209
  }
195
  }
-
 
196
 
210
  uid_t uid = ppwd->pw_uid;
197
  uid_t uid = ppwd->pw_uid;
-
 
198
  uid_t gid = ppwd->pw_gid;
211
 
199
 
212
  char s[NAME_MAX];
200
  char s[NAME_MAX];
213
  strcpy(s, "/tmp/incron.table-XXXXXX");
201
  strcpy(s, "/tmp/incron.table-XXXXXX");
214
 
202
 
215
  uid_t iu = geteuid();
203
  uid_t iu = geteuid();
-
 
204
  uid_t ig = getegid();
216
205
217
  if (seteuid(uid) != 0) {
206
  if (seteuid(uid) != 0 || setegid(gid) != 0) {
218
    fprintf(stderr, "cannot change effective UID to %i: %s\n", (int) uid, strerror(errno));
207
    fprintf(stderr, "cannot change effective UID/GID for user %s: %s\n", user, strerror(errno));
219
    return false;
208
    return false;
220
  }
209
  }
221
 
210
 
222
  int fd = mkstemp(s);
211
  int fd = mkstemp(s);
223
  if (fd == -1) {
212
  if (fd == -1) {
224
    fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno));
213
    fprintf(stderr, "cannot create temporary file: %s\n", strerror(errno));
225
    return false;
214
    return false;
226
  }
215
  }
227
 
216
 
-
 
217
  bool ok = false;
-
 
218
  FILE* out = NULL;
-
 
219
  FILE* in = NULL;
-
 
220
  time_t mt = (time_t) 0;
-
 
221
  const char* e = NULL;
-
 
222
 
228
  if (fchmod(fd, 0644) != 0) {
223
  if (fchmod(fd, 0644) != 0) {
229
    fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno));
224
    fprintf(stderr, "cannot change mode of temporary file: %s\n", strerror(errno));
230
    close(fd);
225
    close(fd);
231
    unlink_suid(s, uid);
-
 
232
    return false;
226
    goto end;
233
  }
227
  }
234
 
228
 
235
  if (seteuid(iu) != 0) {
229
  if (seteuid(iu) != 0 || setegid(ig) != 0) {
236
    fprintf(stderr, "cannot change effective UID: %s\n", strerror(errno));
230
    fprintf(stderr, "cannot change effective UID/GID: %s\n", strerror(errno));
237
    close(fd);
231
    close(fd);
238
    unlink_suid(s, uid);
-
 
239
    return false;
232
    goto end;
240
  }
233
  }
241
   
234
   
242
  FILE* out = fdopen(fd, "w");
235
  out = fdopen(fd, "w");
243
  if (out == NULL) {
236
  if (out == NULL) {
244
    fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno));
237
    fprintf(stderr, "cannot write to temporary file: %s\n", strerror(errno));
245
    close(fd);
238
    close(fd);
246
    unlink_suid(s, uid);
-
 
247
    return false;
239
    goto end;
248
  }
240
  }
249
 
241
 
250
  FILE* in = fopen(tp.c_str(), "r");
242
  in = fopen(tp.c_str(), "r");
251
  if (in == NULL) {
243
  if (in == NULL) {
252
    if (errno == ENOENT) {
244
    if (errno == ENOENT) {
253
      in = fopen("/dev/null", "r");
245
      in = fopen("/dev/null", "r");
254
      if (in == NULL) {
246
      if (in == NULL) {
255
        fprintf(stderr, "cannot get empty table for %s: %s\n", user, strerror(errno));
247
        fprintf(stderr, "cannot get empty table for %s: %s\n", user, strerror(errno));
256
        fclose(out);
248
        fclose(out);
257
        unlink_suid(s, uid);
-
 
258
        return false;
249
        goto end;
259
      }
250
      }
260
    }
251
    }
261
    else {
252
    else {
262
      fprintf(stderr, "cannot read old table for %s: %s\n", user, strerror(errno));
253
      fprintf(stderr, "cannot read old table for %s: %s\n", user, strerror(errno));
263
      fclose(out);
254
      fclose(out);
264
      unlink_suid(s, uid);
-
 
265
      return false;
255
      goto end;
266
    }
256
    }
267
  }
257
  }
268
 
258
 
269
  char buf[1024];
259
  char buf[1024];
270
  while (fgets(buf, 1024, in) != NULL) {
260
  while (fgets(buf, 1024, in) != NULL) {
Line 274... Line 264...
274
  fclose(out);
264
  fclose(out);
275
 
265
 
276
  struct stat st;
266
  struct stat st;
277
  if (stat(s, &st) != 0) {
267
  if (stat(s, &st) != 0) {
278
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
268
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
279
    unlink_suid(s, uid);
-
 
280
    return false;
269
    goto end;
281
  }
270
  }
282
 
271
 
283
  time_t mt = st.st_mtime;
272
  mt = st.st_mtime;
284
 
273
 
285
  const char* e = getenv("EDITOR");
274
  e = getenv("EDITOR");
286
  if (e == NULL)
275
  if (e == NULL)
287
    e = INCRON_DEFAULT_EDITOR;
276
    e = INCRON_DEFAULT_EDITOR;
288
 
277
 
-
 
278
  {
289
  pid_t pid = fork();
279
    pid_t pid = fork();
290
  if (pid == 0) {
280
    if (pid == 0) {
291
    if (setuid(uid) != 0) {
281
      if (setuid(uid) != 0 || setgid(gid) != 0) {
292
      fprintf(stderr, "cannot set user %s: %s\n", user, strerror(errno));
282
        fprintf(stderr, "cannot set user %s: %s\n", user, strerror(errno));
293
      return false;
283
        goto end;
294
    }    
284
      }    
295
   
285
     
296
    execlp(e, e, s, NULL);
286
      execlp(e, e, s, NULL);
297
    _exit(1);
287
      _exit(1);
298
  }
288
    }
299
  else if (pid > 0) {
289
    else if (pid > 0) {
300
    int status;
290
      int status;
301
    if (wait(&status) != pid) {
291
      if (wait(&status) != pid) {
302
      perror("error while waiting for editor");
292
        perror("error while waiting for editor");
303
      unlink_suid(s, uid);
293
        goto end;
-
 
294
      }
-
 
295
      if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) {
-
 
296
        perror("editor finished with error");
304
      return false;
297
        goto end;
-
 
298
      }
305
    }
299
    }
306
    if (!(WIFEXITED(status)) || WEXITSTATUS(status) != 0) {
300
    else {
307
      perror("editor finished with error");
301
      perror("cannot start editor");
308
      unlink_suid(s, uid);
-
 
309
      return false;
302
      goto end;
310
    }
303
    }
311
  }
304
  }
312
  else {
-
 
313
    perror("cannot start editor");
-
 
314
    unlink_suid(s, uid);
-
 
315
    return false;
-
 
316
  }
-
 
317
 
305
 
318
  if (stat(s, &st) != 0) {
306
  if (stat(s, &st) != 0) {
319
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
307
    fprintf(stderr, "cannot stat temporary file: %s\n", strerror(errno));
320
    unlink_suid(s, uid);
-
 
321
    return false;
308
    goto end;
322
  }
309
  }
323
 
310
 
324
  if (st.st_mtime == mt) {
311
  if (st.st_mtime == mt) {
325
    fprintf(stderr, "table unchanged\n");
312
    fprintf(stderr, "table unchanged\n");
326
    unlink_suid(s, uid);
313
    ok = true;
327
    return true;
314
    goto end;
328
  }
315
  }
329
 
316
 
-
 
317
  {
330
  InCronTab ict;
318
    InCronTab ict;
331
  if (!ict.Load(s) || !ict.Save(tp)) {
319
    if (!ict.Load(s) || !ict.Save(tp)) {
332
    fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno));
320
      fprintf(stderr, "cannot move temporary table: %s\n", strerror(errno));
333
    unlink(s);
321
      goto end;
334
    return false;
322
    }
335
  }
323
  }
336
 
324
 
-
 
325
  ok = true;
337
  fprintf(stderr, "table updated\n");
326
  fprintf(stderr, "table updated\n");
338
 
327
 
-
 
328
end:  
-
 
329
 
339
  unlink_suid(s, uid);
330
  unlink(s);
340
  return true;
331
  return ok;
341
}
332
}
342
333
343
334
344
int main(int argc, char** argv)
335
int main(int argc, char** argv)
345
{
336
{