Bug causes the following error message in the following stable releases 2.5.1p1, 2.5.1p3, 2.6.1p1
Amanda Backup Client Hosts Check
--------------------------------
ERROR: NAK mac-mini: user backup from hs-dhgl7ce.msindustries.com is not
allowed to execute the service noop: /Users/amandabackup/.amandahosts:
owned by id 5000, should be 529288
Client check: 1 host checked in 0.859 seconds, 1 problem found
There is no user of UID of 529288 on the machine.
Here is a snip of the amandad log after a modification to add Print statements printing the UID as dereferenced from the pointer in check_user_amandahosts() in common-src/security-util.c
amandad: time 0.187: sec: calling accept_fn
Print uid: 5000
Print UID on entry now: 5000
check_user_amandahosts(host=hs-dhgl7ce.msindustries.com, pwd=0x100400, remoteuse
r=backup, service=selfcheck)
amandad: bsd: processing file: /Users/amandabackup/.amandahosts
amandad: bsd: owner=amandabackup group=wheel mode=600
Print UID after stralloc: 529288
Print UID after fopen: 529288
Print sbuf.st_uid now: 5000
Print UID after fstat: 529288
amandad: bsd: processing line: hs-dhgl7ce.msindustries.com backup="" amdump=""
amandad: bsd: comparing "hs-dhgl7ce.msindustries.com" with
The bug has been fixed by caching the pwd->ps_uid at the start of the function and using the test against that. Also note that the bug behavior changed at some point as the UID changed from 529288 to 0. Suggests a buffer overrun, endianness or thread issues.
Here is the modified check_user_amandahosts() security-util.c (don't forget to modify the top of the file to enable secprintf().
/*
* Check to see if a user is allowed in. This version uses .amandahosts
* Returns -1 on failure, or 0 on success.
*/
char *
check_user_amandahosts(
const char * host,
struct in_addr addr,
struct passwd * pwd,
const char * remoteuser,
const char * service)
{
char *line = NULL;
char *filehost;
const char *fileuser;
char *ptmp = NULL;
char *result = NULL;
FILE *fp = NULL;
int found;
struct stat sbuf;
char n1[NUM_STR_SIZE];
char n2[NUM_STR_SIZE];
int hostmatch;
int usermatch;
char *aservice = NULL;
uid_t tmp_pw_uid = pwd->pw_uid;
secprintf(("Print UID on entry now: %d\n",pwd->pw_uid));
secprintf(("check_user_amandahosts(host=%s, pwd=%p, "
"remoteuser=%s, service=%s)\n",
host, pwd, remoteuser, service));
ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");
#if defined(SHOW_SECURITY_DETAIL) /* { */
show_stat_info(ptmp, "");;
#endif /* } */
secprintf(("Print UID after stralloc: %d\n",pwd->pw_uid));
if ((fp = fopen(ptmp, "r")) == NULL) {
result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL);
amfree(ptmp);
return result;
}
secprintf(("Print UID after fopen: %d\n",pwd->pw_uid));
/*
* Make sure the file is owned by the Amanda user and does not
* have any group/other access allowed.
*/
if (fstat(fileno(fp), &sbuf) != 0) {
result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL);
goto common_exit;
}
secprintf(("Print sbuf.st_uid now: %d\n",sbuf.st_uid));
secprintf(("Print UID after fstat: %d\n",pwd->pw_uid));
/*if (sbuf.st_uid != pwd->pw_uid) {*/
if (sbuf.st_uid != tmp_pw_uid) {
snprintf(n1, SIZEOF(n1), "%ld", (long)sbuf.st_uid);
snprintf(n2, SIZEOF(n2), "%ld", (long)pwd->pw_uid);
result = vstralloc(ptmp, ": ",
"owned by id ", n1,
", should be ", n2,
NULL);
goto common_exit;
}