Skip to content

Commit

Permalink
SUDO Integration - responder 'sudo_timed' option
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrezina authored and sgallagher committed Feb 4, 2012
1 parent 41ef946 commit c9aab1c
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 38 deletions.
2 changes: 2 additions & 0 deletions src/confdb/confdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
#define CONFDB_SUDO_CONF_ENTRY "config/sudo"
#define CONFDB_SUDO_CACHE_TIMEOUT "sudo_cache_timeout"
#define CONFDB_DEFAULT_SUDO_CACHE_TIMEOUT 180
#define CONFDB_SUDO_TIMED "sudo_timed"
#define CONFDB_DEFAULT_SUDO_TIMED false

/* Data Provider */
#define CONFDB_DP_CONF_ENTRY "config/dp"
Expand Down
159 changes: 123 additions & 36 deletions src/db/sysdb_sudo.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#define _XOPEN_SOURCE

#include <talloc.h>
#include <time.h>

#include "db/sysdb.h"
#include "db/sysdb_private.h"
Expand All @@ -32,34 +35,131 @@
} while(0)

/* ==================== Utility functions ==================== */
static char *
get_sudo_time_filter(TALLOC_CTX *mem_ctx)

static errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule,
time_t now,
bool *result)
{
time_t now;
struct tm *tp;
char timebuffer[64];

/* Make sure we have a formatted timestamp for __now__. */
time(&now);
if ((tp = gmtime(&now)) == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, ("unable to get GMT time\n"));
return NULL;
TALLOC_CTX *tmp_ctx = NULL;
const char **values = NULL;
char *tret = NULL;
time_t converted;
struct tm tm;
errno_t ret;
int i;

tmp_ctx = talloc_new(NULL);
NULL_CHECK(tmp_ctx, ret, done);

/*
* From man sudoers.ldap:
*
* A timestamp is in the form yyyymmddHHMMZ.
* If multiple sudoNotBefore entries are present, the *earliest* is used.
* If multiple sudoNotAfter entries are present, the *last one* is used.
*/

/* check for sudoNotBefore */
ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTBEFORE,
tmp_ctx, &values);
if (ret != EOK) {
goto done;
}
if (values != NULL && values[0] != NULL) {
tret = strptime(values[0], SYSDB_SUDO_TIME_FORMAT, &tm);
if (tret == NULL || *tret != '\0') {
DEBUG(SSSDBG_FUNC_DATA, ("Invalid time format!\n"));
ret = EINVAL;
goto done;
}
converted = mktime(&tm);

if (now < converted) {
*result = false;
goto done;
}
}

/* check for sudoNotAfter */
ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTAFTER,
tmp_ctx, &values);
if (ret != EOK) {
goto done;
}
if (values != NULL && values[0] != NULL) {
/* find last value */
for (i = 0; values[i] != NULL; i++) {
// do nothing
}

tret = strptime(values[i - 1], SYSDB_SUDO_TIME_FORMAT, &tm);
if (tret == NULL || *tret != '\0') {
DEBUG(SSSDBG_FUNC_DATA, ("Invalid time format!\n"));
ret = EINVAL;
goto done;
}
converted = mktime(&tm);

/* Format the timestamp according to the RFC. */
if (strftime(timebuffer, sizeof(timebuffer), "%Y%m%d%H%M%SZ", tp) == 0) {
DEBUG(SSSDBG_CRIT_FAILURE, ("unable to format timestamp\n"));
return NULL;
if (now > converted) {
*result = false;
goto done;
}
}

return talloc_asprintf(mem_ctx, "(&(|(!(%s=*))(%s>=%s))"
"(|(!(%s=*))(%s<=%s)))",
SYSDB_SUDO_CACHE_AT_NOTAFTER,
SYSDB_SUDO_CACHE_AT_NOTAFTER,
timebuffer,
SYSDB_SUDO_CACHE_AT_NOTBEFORE,
SYSDB_SUDO_CACHE_AT_NOTBEFORE,
timebuffer);
*result = true;
ret = EOK;

done:
if (ret == ENOENT) {
*result = true;
ret = EOK;
}

talloc_free(tmp_ctx);
return ret;
}

errno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
size_t in_num_rules,
struct sysdb_attrs **in_rules,
time_t now,
size_t *_num_rules,
struct sysdb_attrs ***_rules)
{
size_t num_rules = 0;
struct sysdb_attrs **rules = NULL;
TALLOC_CTX *tmp_ctx = NULL;
bool allowed = false;
errno_t ret;
int i;

tmp_ctx = talloc_new(NULL);
NULL_CHECK(tmp_ctx, ret, done);

if (now == 0) {
now = time(NULL);
}

for (i = 0; i < in_num_rules; i++) {
ret = sysdb_sudo_check_time(in_rules[i], now, &allowed);
if (ret == EOK && allowed) {
num_rules++;
rules = talloc_realloc(tmp_ctx, rules, struct sysdb_attrs *,
num_rules);
NULL_CHECK(rules, ret, done);

rules[num_rules - 1] = in_rules[i];
}
}

*_num_rules = num_rules;
*_rules = talloc_steal(mem_ctx, rules);

ret = EOK;

done:
talloc_free(tmp_ctx);
return ret;
}

errno_t
Expand All @@ -70,7 +170,6 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
TALLOC_CTX *tmp_ctx = NULL;
char *filter = NULL;
char *specific_filter = NULL;
char *time_filter = NULL;
errno_t ret;
int i;

Expand Down Expand Up @@ -123,24 +222,12 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
NULL_CHECK(specific_filter, ret, done);
}

/* build time filter */

if (flags & SYSDB_SUDO_FILTER_TIMED) {
time_filter = get_sudo_time_filter(tmp_ctx);
NULL_CHECK(time_filter, ret, done);
}

/* build global filter */

filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)",
SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_AT_OC);
NULL_CHECK(filter, ret, done);

if (time_filter != NULL) {
filter = talloc_strdup_append(filter, time_filter);
NULL_CHECK(filter, ret, done);
}

if (specific_filter[0] != '\0') {
filter = talloc_asprintf_append(filter, "(|%s)", specific_filter);
NULL_CHECK(filter, ret, done);
Expand Down
10 changes: 9 additions & 1 deletion src/db/sysdb_sudo.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,28 @@
#define SYSDB_SUDO_CACHE_AT_NOTAFTER "sudoNotAfter"
#define SYSDB_SUDO_CACHE_AT_ORDER "sudoOrder"

#define SYSDB_SUDO_TIME_FORMAT "%Y%m%d%H%M%SZ"

/* When constructing a sysdb filter, OR these values to include.. */
#define SYSDB_SUDO_FILTER_NONE 0x00 /* no additional filter */
#define SYSDB_SUDO_FILTER_USERNAME 0x01 /* username */
#define SYSDB_SUDO_FILTER_UID 0x02 /* uid */
#define SYSDB_SUDO_FILTER_GROUPS 0x04 /* groups */
#define SYSDB_SUDO_FILTER_NGRS 0x08 /* netgroups */
#define SYSDB_SUDO_FILTER_TIMED 0x10 /* timed rules */
#define SYSDB_SUDO_FILTER_INCLUDE_ALL 0x20 /* ALL */
#define SYSDB_SUDO_FILTER_INCLUDE_DFL 0x40 /* include cn=default */
#define SYSDB_SUDO_FILTER_USERINFO SYSDB_SUDO_FILTER_USERNAME \
| SYSDB_SUDO_FILTER_UID \
| SYSDB_SUDO_FILTER_GROUPS \
| SYSDB_SUDO_FILTER_NGRS

errno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
size_t in_num_rules,
struct sysdb_attrs **in_rules,
time_t now,
size_t *_num_rules,
struct sysdb_attrs ***_rules);

errno_t
sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
uid_t uid, char **groupnames, unsigned int flags,
Expand Down
11 changes: 11 additions & 0 deletions src/responder/sudo/sudosrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ int sudo_process_init(TALLOC_CTX *mem_ctx,
return ret;
}

/* Get sudo_timed option */
ret = confdb_get_bool(sudo_ctx->rctx->cdb, sudo_ctx,
CONFDB_SUDO_CONF_ENTRY, CONFDB_SUDO_TIMED,
CONFDB_DEFAULT_SUDO_TIMED,
&sudo_ctx->timed);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE, ("Error reading from confdb (%d) [%s]\n",
ret, strerror(ret)));
return ret;
}

/* Initialize in-memory cache */
ret = sudosrv_cache_init(sudo_ctx, 10, &sudo_ctx->cache);
if (ret != EOK) {
Expand Down
21 changes: 20 additions & 1 deletion src/responder/sudo/sudosrv_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "responder/common/responder.h"
#include "responder/common/responder_packet.h"
#include "responder/sudo/sudosrv_private.h"
#include "db/sysdb_sudo.h"

static errno_t sudosrv_cmd_send_reply(struct sudo_cmd_ctx *cmd_ctx,
uint8_t *response_body,
Expand Down Expand Up @@ -90,12 +91,30 @@ errno_t sudosrv_cmd_done(struct sudo_dom_ctx *dctx, int ret)
{
uint8_t *response_body = NULL;
size_t response_len = 0;
size_t num_rules = dctx->res_count;
struct sysdb_attrs **rules = dctx->res;

switch (ret) {
case EOK:
/*
* Parent of dctx->res is in-memory cache, we must not talloc_free it!
*/
if (!dctx->cmd_ctx->sudo_ctx->timed) {
num_rules = dctx->res_count;
rules = dctx->res;
} else {
/* filter rules by time */
ret = sysdb_sudo_filter_rules_by_time(dctx, dctx->res_count,
dctx->res, 0,
&num_rules, &rules);
if (ret != EOK) {
return EFAULT;
}
}

/* send result */
ret = sudosrv_get_sudorules_build_response(dctx->cmd_ctx, SSS_SUDO_ERROR_OK,
dctx->res_count, dctx->res,
num_rules, rules,
&response_body, &response_len);
if (ret != EOK) {
return EFAULT;
Expand Down
1 change: 1 addition & 0 deletions src/responder/sudo/sudosrv_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct sudo_ctx {
* options
*/
int cache_timeout;
bool timed;

/*
* Key: domain for SSS_DP_SUDO_DEFAULTS
Expand Down

0 comments on commit c9aab1c

Please sign in to comment.