version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.4, 2013/07/22 10:46:12
|
Line 1
|
Line 1
|
/* |
/* |
* Copyright (c) 2011 Todd C. Miller <Todd.Miller@courtesan.com> | * Copyright (c) 2011-2013 Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
Line 35
|
Line 35
|
#ifdef HAVE_STRINGS_H |
#ifdef HAVE_STRINGS_H |
# include <strings.h> |
# include <strings.h> |
#endif /* HAVE_STRINGS_H */ |
#endif /* HAVE_STRINGS_H */ |
#ifdef HAVE_SETLOCALE |
|
# include <locale.h> |
|
#endif |
|
#include <pwd.h> |
#include <pwd.h> |
#include <grp.h> |
#include <grp.h> |
#include <time.h> |
#include <time.h> |
Line 46
|
Line 43
|
|
|
struct path_escape { |
struct path_escape { |
const char *name; |
const char *name; |
size_t (*copy_fn)(char *, size_t); | size_t (*copy_fn)(char *, size_t, char *); |
}; |
}; |
|
|
static size_t fill_seq(char *, size_t); |
|
static size_t fill_user(char *, size_t); |
|
static size_t fill_group(char *, size_t); |
|
static size_t fill_runas_user(char *, size_t); |
|
static size_t fill_runas_group(char *, size_t); |
|
static size_t fill_hostname(char *, size_t); |
|
static size_t fill_command(char *, size_t); |
|
|
|
static struct path_escape escapes[] = { |
|
{ "seq", fill_seq }, |
|
{ "user", fill_user }, |
|
{ "group", fill_group }, |
|
{ "runas_user", fill_runas_user }, |
|
{ "runas_group", fill_runas_group }, |
|
{ "hostname", fill_hostname }, |
|
{ "command", fill_command }, |
|
{ NULL, NULL } |
|
}; |
|
|
|
static size_t |
static size_t |
fill_seq(char *str, size_t strsize) | fill_seq(char *str, size_t strsize, char *logdir) |
{ |
{ |
|
#ifdef SUDOERS_NO_SEQ |
|
debug_decl(fill_seq, SUDO_DEBUG_UTIL) |
|
debug_return_size_t(strlcpy(str, "%{seq}", strsize)); |
|
#else |
static char sessid[7]; |
static char sessid[7]; |
int len; |
int len; |
|
debug_decl(fill_seq, SUDO_DEBUG_UTIL) |
|
|
if (sessid[0] == '\0') |
if (sessid[0] == '\0') |
io_nextid(def_iolog_dir, sessid); | io_nextid(logdir, def_iolog_dir, sessid); |
|
|
/* Path is of the form /var/log/sudo-io/00/00/01. */ |
/* Path is of the form /var/log/sudo-io/00/00/01. */ |
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0], |
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0], |
sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]); |
sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]); |
if (len < 0) |
if (len < 0) |
return strsize; /* handle non-standard snprintf() */ | debug_return_size_t(strsize); /* handle non-standard snprintf() */ |
return (size_t)len; | debug_return_size_t(len); |
| #endif /* SUDOERS_NO_SEQ */ |
} |
} |
|
|
static size_t |
static size_t |
fill_user(char *str, size_t strsize) | fill_user(char *str, size_t strsize, char *unused) |
{ |
{ |
return strlcpy(str, user_name, strsize); | debug_decl(fill_user, SUDO_DEBUG_UTIL) |
| debug_return_size_t(strlcpy(str, user_name, strsize)); |
} |
} |
|
|
static size_t |
static size_t |
fill_group(char *str, size_t strsize) | fill_group(char *str, size_t strsize, char *unused) |
{ |
{ |
struct group *grp; |
struct group *grp; |
size_t len; |
size_t len; |
|
debug_decl(fill_group, SUDO_DEBUG_UTIL) |
|
|
if ((grp = sudo_getgrgid(user_gid)) != NULL) { |
if ((grp = sudo_getgrgid(user_gid)) != NULL) { |
len = strlcpy(str, grp->gr_name, strsize); |
len = strlcpy(str, grp->gr_name, strsize); |
gr_delref(grp); | sudo_gr_delref(grp); |
} else { |
} else { |
len = strlen(str); |
len = strlen(str); |
len = snprintf(str + len, strsize - len, "#%u", |
len = snprintf(str + len, strsize - len, "#%u", |
(unsigned int) user_gid); |
(unsigned int) user_gid); |
} |
} |
return len; | debug_return_size_t(len); |
} |
} |
|
|
static size_t |
static size_t |
fill_runas_user(char *str, size_t strsize) | fill_runas_user(char *str, size_t strsize, char *unused) |
{ |
{ |
return strlcpy(str, runas_pw->pw_name, strsize); | debug_decl(fill_runas_user, SUDO_DEBUG_UTIL) |
| debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize)); |
} |
} |
|
|
static size_t |
static size_t |
fill_runas_group(char *str, size_t strsize) | fill_runas_group(char *str, size_t strsize, char *unused) |
{ |
{ |
struct group *grp; |
struct group *grp; |
size_t len; |
size_t len; |
|
debug_decl(fill_runas_group, SUDO_DEBUG_UTIL) |
|
|
if (runas_gr != NULL) { |
if (runas_gr != NULL) { |
len = strlcpy(str, runas_gr->gr_name, strsize); |
len = strlcpy(str, runas_gr->gr_name, strsize); |
} else { |
} else { |
if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) { |
if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) { |
len = strlcpy(str, grp->gr_name, strsize); |
len = strlcpy(str, grp->gr_name, strsize); |
gr_delref(grp); | sudo_gr_delref(grp); |
} else { |
} else { |
len = strlen(str); |
len = strlen(str); |
len = snprintf(str + len, strsize - len, "#%u", |
len = snprintf(str + len, strsize - len, "#%u", |
(unsigned int) runas_pw->pw_gid); |
(unsigned int) runas_pw->pw_gid); |
} |
} |
} |
} |
return len; | debug_return_size_t(len); |
} |
} |
|
|
static size_t |
static size_t |
fill_hostname(char *str, size_t strsize) | fill_hostname(char *str, size_t strsize, char *unused) |
{ |
{ |
return strlcpy(str, user_shost, strsize); | debug_decl(fill_hostname, SUDO_DEBUG_UTIL) |
| debug_return_size_t(strlcpy(str, user_shost, strsize)); |
} |
} |
|
|
static size_t |
static size_t |
fill_command(char *str, size_t strsize) | fill_command(char *str, size_t strsize, char *unused) |
{ |
{ |
return strlcpy(str, user_base, strsize); | debug_decl(fill_command, SUDO_DEBUG_UTIL) |
| debug_return_size_t(strlcpy(str, user_base, strsize)); |
} |
} |
|
|
|
/* Note: "seq" must be first in the list. */ |
|
static struct path_escape io_path_escapes[] = { |
|
{ "seq", fill_seq }, |
|
{ "user", fill_user }, |
|
{ "group", fill_group }, |
|
{ "runas_user", fill_runas_user }, |
|
{ "runas_group", fill_runas_group }, |
|
{ "hostname", fill_hostname }, |
|
{ "command", fill_command }, |
|
{ NULL, NULL } |
|
}; |
|
|
/* |
/* |
* Concatenate dir + file, expanding any escape sequences. |
* Concatenate dir + file, expanding any escape sequences. |
* Returns the concatenated path and sets slashp point to |
* Returns the concatenated path and sets slashp point to |
Line 158 expand_iolog_path(const char *prefix, const char *dir,
|
Line 160 expand_iolog_path(const char *prefix, const char *dir,
|
{ |
{ |
size_t len, prelen = 0; |
size_t len, prelen = 0; |
char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX]; |
char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX]; |
|
char *slash = NULL; |
const char *endbrace, *src = dir; |
const char *endbrace, *src = dir; |
int pass, strfit; | struct path_escape *escapes = NULL; |
| int pass, oldlocale; |
| bool strfit; |
| debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL) |
|
|
/* Expanded path must be <= PATH_MAX */ |
/* Expanded path must be <= PATH_MAX */ |
if (prefix != NULL) |
if (prefix != NULL) |
Line 180 expand_iolog_path(const char *prefix, const char *dir,
|
Line 186 expand_iolog_path(const char *prefix, const char *dir,
|
file++; |
file++; |
|
|
for (pass = 0; pass < 3; pass++) { |
for (pass = 0; pass < 3; pass++) { |
strfit = FALSE; | strfit = false; |
switch (pass) { |
switch (pass) { |
case 0: |
case 0: |
src = dir; |
src = dir; |
|
escapes = io_path_escapes + 1; /* skip "%{seq}" */ |
break; |
break; |
case 1: |
case 1: |
/* Trim trailing slashes from dir component. */ |
/* Trim trailing slashes from dir component. */ |
while (dst - path - 1 > prelen && dst[-1] == '/') |
while (dst - path - 1 > prelen && dst[-1] == '/') |
dst--; |
dst--; |
if (slashp) | /* The NUL will be replaced with a '/' at the end. */ |
*slashp = dst; | if (dst + 1 >= pathend) |
src = "/"; | goto bad; |
break; | slash = dst++; |
| continue; |
case 2: |
case 2: |
src = file; |
src = file; |
|
escapes = io_path_escapes; |
break; |
break; |
} |
} |
dst0 = dst; |
dst0 = dst; |
Line 211 expand_iolog_path(const char *prefix, const char *dir,
|
Line 220 expand_iolog_path(const char *prefix, const char *dir,
|
break; |
break; |
} |
} |
if (esc->name != NULL) { |
if (esc->name != NULL) { |
len = esc->copy_fn(dst, (size_t)(pathend - dst)); | len = esc->copy_fn(dst, (size_t)(pathend - dst), |
| path + prelen); |
if (len >= (size_t)(pathend - dst)) |
if (len >= (size_t)(pathend - dst)) |
goto bad; |
goto bad; |
dst += len; |
dst += len; |
Line 242 expand_iolog_path(const char *prefix, const char *dir,
|
Line 252 expand_iolog_path(const char *prefix, const char *dir,
|
time(&now); |
time(&now); |
timeptr = localtime(&now); |
timeptr = localtime(&now); |
|
|
#ifdef HAVE_SETLOCALE | /* Use sudoers locale for strftime() */ |
if (!setlocale(LC_ALL, def_sudoers_locale)) { | sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale); |
warningx(_("unable to set locale to \"%s\", using \"C\""), | |
def_sudoers_locale); | |
setlocale(LC_ALL, "C"); | |
} | |
#endif | |
/* We only calls strftime() on the current part of the buffer. */ |
/* We only calls strftime() on the current part of the buffer. */ |
tmpbuf[sizeof(tmpbuf) - 1] = '\0'; |
tmpbuf[sizeof(tmpbuf) - 1] = '\0'; |
len = strftime(tmpbuf, sizeof(tmpbuf), dst0, timeptr); |
len = strftime(tmpbuf, sizeof(tmpbuf), dst0, timeptr); |
|
|
#ifdef HAVE_SETLOCALE | /* Restore old locale. */ |
setlocale(LC_ALL, ""); | sudoers_setlocale(oldlocale, NULL); |
#endif | |
if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0') |
if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0') |
goto bad; /* strftime() failed, buf too small? */ |
goto bad; /* strftime() failed, buf too small? */ |
|
|
Line 266 expand_iolog_path(const char *prefix, const char *dir,
|
Line 272 expand_iolog_path(const char *prefix, const char *dir,
|
*dst = '\0'; |
*dst = '\0'; |
} |
} |
} |
} |
|
if (slashp) |
|
*slashp = slash; |
|
*slash = '/'; |
|
|
return path; | debug_return_str(path); |
bad: |
bad: |
efree(path); |
efree(path); |
return NULL; | debug_return_str(NULL); |
} |
} |