1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* Utility functions for krb5-sync testing.
*
* Some additional test functions used by more than one program in the
* krb5-sync test suite.
*
* Written by Russ Allbery <eagle@eyrie.org>
* Copyright 2012, 2013
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
#include <config.h>
#include <portable/system.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <tests/tap/basic.h>
#include <tests/tap/string.h>
#include <tests/tap/sync.h>
/*
* Format the user for queue file naming. This just replaces all slashes with
* periods and returns the new user as a newly-allocated string.
*/
static char *
munge_user(const char *user)
{
char *munged_user, *p;
munged_user = bstrdup(user);
for (p = munged_user; *p != '\0'; p++)
if (*p == '/')
*p = '.';
return munged_user;
}
/*
* Block processing by creating a dummy queue file. Takes the queue
* directory, the username (as used for queuing), and the operation to block.
* Calls bail on failure.
*/
void
sync_queue_block(const char *queue, const char *user, const char *op)
{
int fd;
char *file, *munged_user;
munged_user = munge_user(user);
basprintf(&file, "%s/%s-ad-%s-19700101T000000Z", queue, munged_user, op);
free(munged_user);
fd = open(file, O_CREAT | O_WRONLY, 0666);
if (fd < 0)
sysbail("cannot create blocking queue file %s", file);
close(fd);
free(file);
}
/*
* Undo the effects of sync_queue_block and call bail if we can't find the
* corresponding file.
*/
void
sync_queue_unblock(const char *queue, const char *user, const char *op)
{
char *file, *munged_user;
munged_user = munge_user(user);
basprintf(&file, "%s/%s-ad-%s-19700101T000000Z", queue, munged_user, op);
free(munged_user);
if (unlink(file) < 0)
sysbail("cannot delete blocking queue file %s", file);
free(file);
}
/*
* Internal helper function for queue checks. Takes the queue path, the user,
* the operation, and (optionally) the password. Reports results with the
* normal ok functions and calls bail on system failures.
*/
static void
queue_check(const char *queue, const char *user, const char *op,
const char *password)
{
char *path, *wanted, *munged_user;
const char *path_op;
time_t now, timestamp;
struct tm *date;
struct stat st;
FILE *file;
char buffer[BUFSIZ];
/* Find the queue file. It should have a nearby timestamp. */
path = NULL;
now = time(NULL);
path_op = (strcmp("disable", op) == 0) ? "enable" : op;
munged_user = munge_user(user);
for (timestamp = now - 1; timestamp <= now; timestamp++) {
date = gmtime(×tamp);
basprintf(&path, "%s/%s-ad-%s-%04d%02d%02dT%02d%02d%02dZ-00", queue,
munged_user, path_op, date->tm_year + 1900, date->tm_mon + 1,
date->tm_mday, date->tm_hour, date->tm_min, date->tm_sec);
if (access(path, F_OK) == 0)
break;
free(path);
path = NULL;
}
free(munged_user);
/* Check that we found a queued change. */
ok(path != NULL, "%s for %s was queued", op, user);
if (path == NULL) {
if (password == NULL)
ok_block(4, false, "No queued change to check");
else
ok_block(5, false, "No queued change to check");
free(path);
return;
}
/* Check the file mode. */
if (stat(path, &st) < 0)
sysbail("cannot stat %s", path);
is_int(0600, st.st_mode & 0777, "...mode of queue file is correct");
/* Open the file and check the data. */
file = fopen(path, "r");
if (file == NULL)
sysbail("cannot open %s", path);
if (fgets(buffer, sizeof(buffer), file) == NULL)
buffer[0] = '\0';
basprintf(&wanted, "%s\n", user);
is_string(wanted, buffer, "...queued user is correct");
free(wanted);
if (fgets(buffer, sizeof(buffer), file) == NULL)
buffer[0] = '\0';
is_string("ad\n", buffer, "...queued domain is correct");
if (fgets(buffer, sizeof(buffer), file) == NULL)
buffer[0] = '\0';
basprintf(&wanted, "%s\n", op);
is_string(wanted, buffer, "...queued operation is correct");
free(wanted);
if (password != NULL) {
if (fgets(buffer, sizeof(buffer), file) == NULL)
buffer[0] = '\0';
basprintf(&wanted, "%s\n", password);
is_string(wanted, buffer, "...queued password is correct");
free(wanted);
}
fclose(file);
/* Remove the queue file. */
if (unlink(path) < 0)
sysbail("cannot delete %s", path);
free(path);
}
/*
* Look for an enable or disable change queued in the past second and check
* that it matches the provided parameters. Takes the queue, the username,
* and whether the account should be enabled. Reports results with the normal
* ok functions.
*/
void
sync_queue_check_enable(const char *queue, const char *user, bool enable)
{
queue_check(queue, user, enable ? "enable" : "disable", NULL);
}
/*
* Look for a password change queued in the past second and check that it
* matches the provided parameters. Takes the queue, the username, and the
* password. Reports results with the normal ok functions.
*/
void
sync_queue_check_password(const char *queue, const char *user,
const char *password)
{
queue_check(queue, user, "password", password);
}
|