diff --git a/QUICKSTART b/QUICKSTART index 1b733149..08715c47 100644 --- a/QUICKSTART +++ b/QUICKSTART @@ -14,14 +14,14 @@ MUNGE Installation Guide Since authentication is based on UID and GID, users authenticating with MUNGE need to have consistent UID/GID mappings across all nodes - within the security realm. Since the "munge" user is a system account, - its UID and GID do not need to be kept in sync across nodes. + within the security domain. Since the "munge" user is a system + account, its UID and GID do not need to be kept in sync across nodes. C. Keep system clocks in sync MUNGE credentials are valid for a limited time defined by their embedded time-to-live value (5 minutes by default). The fastest and slowest - system clocks across all nodes within the security realm should be + system clocks across all nodes within the security domain should be within this time interval. 2. Software dependencies @@ -237,9 +237,10 @@ MUNGE Installation Guide A. Creating a key - All munged daemons within a security realm share a common key. This key - is used to cryptographically protect the credential. Consequently, - credentials are only valid within a given security realm. + All munged daemons within a security domain share a common key. This + key is used to cryptographically protect the credential. + Consequently, credentials are only valid within a given security + domain. The "mungekey" executable is the key management utility. To ensure the key file maintains the correct ownership and permissions, it should @@ -252,7 +253,7 @@ MUNGE Installation Guide be owned by the same user ID that will run the munged daemon process, and its permissions should be set to 0600. Additionally, this key file will need to be securely propagated (e.g., via ssh) to all hosts - within the security realm. + within the security domain. B. Setting command-line options @@ -460,7 +461,7 @@ MUNGE Installation Guide A key has not been created. See mungekey(8). Note that this file will need to be securely propagated to all hosts within the - security realm. + security domain. 9. munged: Error: Found pid 1234 bound to socket "/run/munge/munge.socket.2" diff --git a/README b/README index f5e19a55..0a3c8957 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ INTRODUCTION scalable for use in an HPC cluster environment. It provides a portable API for encoding the user's identity into a tamper-proof credential that can be obtained by an untrusted client and forwarded by untrusted - intermediaries within a security realm. Clients within this realm can + intermediaries within a security domain. Clients within this domain can create and validate credentials without the use of root privileges, reserved ports, or platform-specific methods. @@ -38,7 +38,7 @@ USAGE MUNGE service, either via the munge_encode() C library call or the munge executable. The encoded credential contains the UID and GID of the originating process. This process sends the credential to another - process within the security realm as a means of proving its identity. + process within the security domain as a means of proving its identity. The receiving process validates the credential with the use of its local MUNGE service, either via the munge_decode() C library call or the unmunge executable. The decoded credential provides the receiving process with a @@ -49,10 +49,10 @@ USAGE DETAILS The contents of the credential (including any optional payload data) are - encrypted with a key shared by all munged daemons within the security realm. + encrypted with a key shared by all munged daemons within the security domain. The integrity of the credential is ensured by a message authentication code (MAC). The credential is valid for a limited time defined by its - time-to-live (TTL); this presumes clocks within a security realm are + time-to-live (TTL); this presumes clocks within a security domain are in sync. Unexpired credentials are tracked by the local munged daemon in order to prevent replay attacks on a given host. Decoding of a credential can be restricted to a particular user and/or group ID. The payload data diff --git a/README.md b/README.md index 08642130..97072b2e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ and validating user credentials. It is designed to be highly scalable for use in an HPC cluster environment. It provides a portable API for encoding the user's identity into a tamper-proof credential that can be obtained by an untrusted client and forwarded by untrusted intermediaries within a security -realm. Clients within this realm can create and validate credentials without +domain. Clients within this domain can create and validate credentials without the use of root privileges, reserved ports, or platform-specific methods. - [Overview](../../wiki/Man-7-munge) diff --git a/munge.spec.in b/munge.spec.in index 0db1a005..6f10e1c0 100644 --- a/munge.spec.in +++ b/munge.spec.in @@ -40,7 +40,7 @@ and validating user credentials. It is designed to be highly scalable for use in an HPC cluster environment. It provides a portable API for encoding the user's identity into a tamper-proof credential that can be obtained by an untrusted client and forwarded by untrusted intermediaries within a security -realm. Clients within this realm can create and validate credentials without +domain. Clients within this domain can create and validate credentials without the use of root privileges, reserved ports, or platform-specific methods. %package devel diff --git a/src/libmunge/munge_ctx.3.in b/src/libmunge/munge_ctx.3.in index 24c0c93c..d2f302a6 100644 --- a/src/libmunge/munge_ctx.3.in +++ b/src/libmunge/munge_ctx.3.in @@ -102,7 +102,7 @@ Get or set the compression type (see \fBCOMPRESSION TYPES\fR). \fBMUNGE_OPT_REALM\fR , \fIchar *\fR Get or set the security realm, where the \fIchar *\fR type is a NUL-terminated character string. The string returned by \fBmunge_ctx_get\fR() should not -be freed or modified by the caller. \fBNOT CURRENTLY SUPPORTED\fR. +be freed or modified by the caller. .TP \fBMUNGE_OPT_TTL\fR , \fIint\fR Get or set the time-to-live (in seconds) (see \fBTTL TYPES\fR). This value diff --git a/src/munge/munge.c b/src/munge/munge.c index 37c19290..9aa7f292 100644 --- a/src/munge/munge.c +++ b/src/munge/munge.c @@ -77,6 +77,7 @@ struct option long_opts[] = { { "gid", required_argument, NULL, 'G' }, { "ttl", required_argument, NULL, 't' }, { "socket", required_argument, NULL, 'S' }, + { "realm", required_argument, NULL, 'R' }, { NULL, 0, NULL, 0 } }; @@ -391,6 +392,15 @@ parse_cmdline (conf_t conf, int argc, char **argv) munge_ctx_strerror (conf->ctx)); } break; + case 'R': + e = munge_ctx_set (conf->ctx, MUNGE_OPT_REALM, optarg); + if (e != EMUNGE_SUCCESS) { + log_err (EMUNGE_SNAFU, LOG_ERR, + "Failed to set realm: %s", + munge_ctx_strerror (conf->ctx)); + } + break; + case '?': if (optopt > 0) { log_err (EMUNGE_SNAFU, LOG_ERR, @@ -517,6 +527,10 @@ display_help (char *prog) printf (" %*s %s\n", w, "-S, --socket=PATH", "Specify local socket for munged"); + printf (" %*s %s\n", w, "-R, --realm=REALM", + "Specify security realm"); + + printf ("\n"); printf ("By default, payload read from stdin, " "credential written to stdout.\n\n"); diff --git a/src/munge/unmunge.c b/src/munge/unmunge.c index cec14bd9..a2b240c2 100644 --- a/src/munge/unmunge.c +++ b/src/munge/unmunge.c @@ -105,6 +105,7 @@ void display_gid (conf_t conf); void display_uid_restriction (conf_t conf); void display_gid_restriction (conf_t conf); void display_length (conf_t conf); +void display_realm (conf_t conf); void display_data (conf_t conf); int key_str_to_val (const char *str); const char * key_val_to_str (int val); @@ -128,6 +129,7 @@ typedef enum { MUNGE_KEY_UID_RESTRICTION, MUNGE_KEY_GID_RESTRICTION, MUNGE_KEY_LENGTH, + MUNGE_KEY_REALM, MUNGE_KEY_LAST } munge_key_t; @@ -145,6 +147,7 @@ display_key_t munge_keys[] = { { MUNGE_KEY_UID_RESTRICTION, "UID_RESTRICTION", display_uid_restriction }, { MUNGE_KEY_GID_RESTRICTION, "GID_RESTRICTION", display_gid_restriction }, { MUNGE_KEY_LENGTH, "LENGTH", display_length }, + { MUNGE_KEY_REALM , "REALM", display_realm }, { MUNGE_KEY_LAST, NULL, NULL } }; @@ -194,6 +197,7 @@ struct conf { char key[ MUNGE_KEY_LAST ]; /* key flag array (true if enabled) */ int key_width; /* num chars reserved for key field */ unsigned got_numeric:1; /* flag for NUMERIC option */ + unsigned got_keys:1; /* flag for KEYS option */ }; @@ -280,6 +284,7 @@ create_conf (void) } conf->key_width = maxlen + 1; /* separate longest key by one space */ conf->got_numeric = 0; + conf->got_keys = 0; return (conf); } @@ -337,7 +342,6 @@ destroy_conf (conf_t conf) void parse_cmdline (conf_t conf, int argc, char **argv) { - int got_keys = 0; char *prog; int c; munge_err_t e; @@ -382,7 +386,7 @@ parse_cmdline (conf_t conf, int argc, char **argv) conf->fn_out = optarg; break; case 'k': - got_keys = 1; + conf->got_keys = 1; parse_keys (conf, optarg); break; case 'K': @@ -448,7 +452,7 @@ parse_cmdline (conf_t conf, int argc, char **argv) } /* Enable all metadata keys if a subset was not specified. */ - if (!got_keys) { + if (!conf->got_keys) { for (i = 0; i < MUNGE_KEY_LAST; i++) { conf->key[i] = 1; } @@ -1035,6 +1039,23 @@ display_length (conf_t conf) return; } +void +display_realm (conf_t conf) +{ + const char *key, *s; + int num_spaces; + munge_err_t err; + + assert (conf != NULL); + + key = key_val_to_str (MUNGE_KEY_REALM); + num_spaces = conf->key_width - strlen (key); + err = munge_ctx_get (conf->ctx, MUNGE_OPT_REALM, &s); + if (s || conf->got_keys) + fprintf (conf->fp_meta, "%s:%*c%s\n", key, num_spaces, 0x20, s); + return; +} + void display_data (conf_t conf) diff --git a/src/munged/conf.c b/src/munged/conf.c index 550b4162..cd2698c4 100644 --- a/src/munged/conf.c +++ b/src/munged/conf.c @@ -135,6 +135,10 @@ static void _conf_set_origin_addr (conf_t conf); static int _conf_open_keyfile (const char *keyfile, int got_force); +static conf_realm_t _conf_create_realm (conf_t conf, const char *realm_str); + +static int _conf_destroy_realm (void *data, const void *key, void *arg); + /***************************************************************************** * Global Variables @@ -151,6 +155,7 @@ conf_t create_conf (void) { conf_t conf; + conf_realm_t realm; if (!(conf = malloc (sizeof (struct conf)))) { log_errno (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to allocate conf"); @@ -197,14 +202,6 @@ create_conf (void) log_errno (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to copy seed-file name default string"); } - if (!(conf->key_name = strdup (MUNGE_KEYFILE_PATH))) { - log_errno (EMUNGE_NO_MEMORY, LOG_ERR, - "Failed to copy key-file name default string"); - } - conf->dek_key = NULL; - conf->dek_key_len = 0; - conf->mac_key = NULL; - conf->mac_key_len = 0; conf->origin_name = NULL; conf->origin_ifname = NULL; memset (&conf->addr, 0, sizeof (conf->addr)); @@ -226,9 +223,57 @@ create_conf (void) } #endif /* AUTH_METHOD_RECVFD_MKFIFO || AUTH_METHOD_RECVFD_MKNOD */ + conf->realms = hash_create (1023, + (hash_key_f) hash_key_string, + (hash_cmp_f) strcmp, + (hash_del_f) free); + if (!conf->realms) + log_errno (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to allocate realms hash"); + + realm = _conf_create_realm(conf, ""); + if (!(realm->key_name = strdup (MUNGE_KEYFILE_PATH))) + log_errno (EMUNGE_NO_MEMORY, LOG_ERR, + "Failed to copy key-file name default string"); + return (conf); } +static conf_realm_t _conf_create_realm (conf_t conf, const char *realm_str) +{ + conf_realm_t realm; + + realm = malloc (sizeof *realm); + if (!realm) + log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to allocate conf realm"); + + realm_str = strdup (realm_str); + if (!realm_str) { + free (realm); + log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to copy realm_str"); + } + + realm->key_name = NULL; + realm->dek_key = NULL; + realm->dek_key_len = 0; + realm->mac_key = NULL; + realm->mac_key_len = 0; + + void *ret = hash_insert(conf->realms, realm_str, realm); + if (!ret) { + free ((void*)realm_str); + free (realm); + } + + return ret; +} + +static conf_realm_t _conf_get_or_create_realm (conf_t conf, const char *realm_str) +{ + conf_realm_t realm = get_realm(conf, realm_str); + if (!realm) + realm = _conf_create_realm(conf, realm_str); + return realm; +} void destroy_conf (conf_t conf, int do_unlink) @@ -277,20 +322,6 @@ destroy_conf (conf_t conf, int do_unlink) free (conf->seed_name); conf->seed_name = NULL; } - if (conf->key_name) { - free (conf->key_name); - conf->key_name = NULL; - } - if (conf->dek_key) { - memburn (conf->dek_key, 0, conf->dek_key_len); - free (conf->dek_key); - conf->dek_key = NULL; - } - if (conf->mac_key) { - memburn (conf->mac_key, 0, conf->mac_key_len); - free (conf->mac_key); - conf->mac_key = NULL; - } if (conf->origin_name) { free (conf->origin_name); conf->origin_name = NULL; @@ -307,11 +338,43 @@ destroy_conf (conf_t conf, int do_unlink) free (conf->auth_client_dir); conf->auth_client_dir = NULL; } + if (conf->realms) { + hash_for_each (conf->realms, _conf_destroy_realm, NULL); + /* hash_destroy (conf->realms); */ + /* conf->realms = NULL; */ + } + free (conf); return; } +static int _conf_destroy_realm (void *data, const void *key, void *arg) +{ + conf_realm_t realm = data; + if (!realm) + abort(); + + return 0; + + if (realm->key_name) { + free (realm->key_name); + realm->key_name = NULL; + } + if (realm->dek_key) { + memburn (realm->dek_key, 0, realm->dek_key_len); + free (realm->dek_key); + realm->dek_key = NULL; + } + if (realm->mac_key) { + memburn (realm->mac_key, 0, realm->mac_key_len); + free (realm->mac_key); + realm->mac_key = NULL; + } + + return 1; +} + void parse_cmdline (conf_t conf, int argc, char **argv) @@ -320,6 +383,7 @@ parse_cmdline (conf_t conf, int argc, char **argv) int c; long l; char *p; + conf_realm_t realm; assert (conf != NULL); @@ -404,7 +468,8 @@ parse_cmdline (conf_t conf, int argc, char **argv) conf->gids_update_secs = l; break; case OPT_KEY_FILE: - _conf_set_string (&conf->key_name, optarg, conf->cwd, + realm = _conf_get_or_create_realm(conf, ""); + _conf_set_string (&realm->key_name, optarg, conf->cwd, "key-file name"); break; case OPT_LOG_FILE: @@ -540,9 +605,8 @@ write_origin_addr (conf_t conf) return; } - void -create_subkeys (conf_t conf) +create_subkeys (conf_t conf, conf_realm_t realm) { int fd; int n; @@ -552,28 +616,28 @@ create_subkeys (conf_t conf) md_ctx mac_ctx; assert (conf != NULL); - assert (conf->dek_key == NULL); - assert (conf->mac_key == NULL); + assert (realm->dek_key == NULL); + assert (realm->mac_key == NULL); /* Allocate memory for subkeys. */ - if ((conf->dek_key_len = md_size (MUNGE_MAC_SHA1)) <= 0) { + if ((realm->dek_key_len = md_size (MUNGE_MAC_SHA1)) <= 0) { log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to determine DEK key length"); } - if (!(conf->dek_key = malloc (conf->dek_key_len))) { + if (!(realm->dek_key = malloc (realm->dek_key_len))) { log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to allocate %d bytes for cipher subkey", - conf->dek_key_len); + realm->dek_key_len); } - if ((conf->mac_key_len = md_size (MUNGE_MAC_SHA1)) <= 0) { + if ((realm->mac_key_len = md_size (MUNGE_MAC_SHA1)) <= 0) { log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to determine MAC key length"); } - if (!(conf->mac_key = malloc (conf->mac_key_len))) { + if (!(realm->mac_key = malloc (realm->mac_key_len))) { log_err (EMUNGE_NO_MEMORY, LOG_ERR, "Failed to allocate %d bytes for MAC subkey", - conf->mac_key_len); + realm->mac_key_len); } if (md_init (&dek_ctx, MUNGE_MAC_SHA1) < 0) { log_err (EMUNGE_SNAFU, LOG_ERR, @@ -581,7 +645,7 @@ create_subkeys (conf_t conf) } /* Compute keyfile's message digest. */ - fd = _conf_open_keyfile (conf->key_name, conf->got_force); + fd = _conf_open_keyfile (realm->key_name, conf->got_force); assert (fd >= 0); n_total = 0; @@ -593,7 +657,7 @@ create_subkeys (conf_t conf) continue; if (n < 0) log_errno (EMUNGE_SNAFU, LOG_ERR, - "Failed to read keyfile \"%s\"", conf->key_name); + "Failed to read keyfile \"%s\"", realm->key_name); if (md_update (&dek_ctx, buf, n) < 0) log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to compute subkeys: Cannot update md ctx"); @@ -601,7 +665,7 @@ create_subkeys (conf_t conf) } if (close (fd) < 0) { log_errno (EMUNGE_SNAFU, LOG_ERR, - "Failed to close keyfile \"%s\"", conf->key_name); + "Failed to close keyfile \"%s\"", realm->key_name); } if (n_total < MUNGE_KEY_LEN_MIN_BYTES) { log_err (EMUNGE_SNAFU, LOG_ERR, @@ -613,28 +677,35 @@ create_subkeys (conf_t conf) } /* Append "1" to keyfile in order to compute cipher subkey. */ - n = conf->dek_key_len; + n = realm->dek_key_len; if ( (md_update (&dek_ctx, "1", 1) < 0) - || (md_final (&dek_ctx, conf->dek_key, &n) < 0) + || (md_final (&dek_ctx, realm->dek_key, &n) < 0) || (md_cleanup (&dek_ctx) < 0) ) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to compute cipher subkey"); } - assert (n <= conf->dek_key_len); + assert (n <= realm->dek_key_len); /* Append "2" to keyfile in order to compute mac subkey. */ - n = conf->mac_key_len; + n = realm->mac_key_len; if ( (md_update (&mac_ctx, "2", 1) < 0) - || (md_final (&mac_ctx, conf->mac_key, &n) < 0) + || (md_final (&mac_ctx, realm->mac_key, &n) < 0) || (md_cleanup (&mac_ctx) < 0) ) { log_err (EMUNGE_SNAFU, LOG_ERR, "Failed to compute MAC subkey"); } - assert (n <= conf->mac_key_len); + assert (n <= realm->mac_key_len); return; } +conf_realm_t get_realm(conf_t conf, const char *realm) +{ + if (!realm) + realm = ""; + return hash_find(conf->realms, realm); +} + /***************************************************************************** * Internal Functions *****************************************************************************/ diff --git a/src/munged/conf.h b/src/munged/conf.h index 174b1123..af56a6f2 100644 --- a/src/munged/conf.h +++ b/src/munged/conf.h @@ -34,12 +34,23 @@ #include #include #include "gids.h" +#include "hash.h" /***************************************************************************** * Data Types *****************************************************************************/ +struct conf_realm { + char *key_name; /* symmetric key filename */ + unsigned char *dek_key; /* subkey for cipher ops */ + int dek_key_len; /* length of cipher subkey */ + unsigned char *mac_key; /* subkey for mac ops */ + int mac_key_len; /* length of mac subkey */ +}; + +typedef struct conf_realm * conf_realm_t; + struct conf { int ld; /* listening socket descriptor */ unsigned got_benchmark:1; /* flag for BENCHMARK option */ @@ -66,11 +77,7 @@ struct conf { char *pidfile_name; /* daemon pidfile name */ char *socket_name; /* unix domain socket filename */ char *seed_name; /* random seed filename */ - char *key_name; /* symmetric key filename */ - unsigned char *dek_key; /* subkey for cipher ops */ - int dek_key_len; /* length of cipher subkey */ - unsigned char *mac_key; /* subkey for mac ops */ - int mac_key_len; /* length of mac subkey */ + hash_t realms; /* map of security realms by name */ char *origin_name; /* origin addr hostname/IP string */ char *origin_ifname; /* origin addr n/w interface name */ struct in_addr addr; /* origin addr in n/w byte order */ @@ -106,7 +113,9 @@ void process_conf (conf_t conf); void write_origin_addr (conf_t conf); -void create_subkeys (conf_t conf); +void create_subkeys (conf_t conf, conf_realm_t realm); + +conf_realm_t get_realm (conf_t conf, const char *realm); #endif /* !MUNGE_CONF_H */ diff --git a/src/munged/dec.c b/src/munged/dec.c index 7ce7cf73..dfc684dc 100644 --- a/src/munged/dec.c +++ b/src/munged/dec.c @@ -558,6 +558,12 @@ dec_decrypt (munge_cred_t c) if (m->cipher == MUNGE_CIPHER_NONE) { return (0); } + + conf_realm_t realm = get_realm(conf, m->realm_str); + if (!realm) + return (m_msg_set_err (m, EMUNGE_BAD_REALM, + strdup ("Unknown realm"))); + /* Compute DEK. * msg-dek = MAC (msg-mac) using DEK subkey */ @@ -570,7 +576,7 @@ dec_decrypt (munge_cred_t c) assert (c->dek_len <= sizeof (c->dek)); n = c->dek_len; - if (mac_block (m->mac, conf->dek_key, conf->dek_key_len, + if (mac_block (m->mac, realm->dek_key, realm->dek_key_len, c->dek, &n, c->mac, c->mac_len) < 0) { return (m_msg_set_err (m, EMUNGE_SNAFU, strdup ("Failed to compute DEK"))); @@ -647,9 +653,14 @@ dec_validate_mac (munge_cred_t c) unsigned char mac[MAX_MAC]; /* message authentication code */ int n; /* all-purpose int */ + conf_realm_t realm = get_realm (conf, m->realm_str); + if (!realm) + return (m_msg_set_err (m, EMUNGE_BAD_REALM, + strdup ("Unknown realm"))); + /* Compute MAC. */ - if (mac_init (&x, m->mac, conf->mac_key, conf->mac_key_len) < 0) { + if (mac_init (&x, m->mac, realm->mac_key, realm->mac_key_len) < 0) { goto err; } if (mac_update (&x, c->outer, c->outer_len) < 0) { diff --git a/src/munged/enc.c b/src/munged/enc.c index 7aa5bd76..9f926551 100644 --- a/src/munged/enc.c +++ b/src/munged/enc.c @@ -537,9 +537,13 @@ enc_mac (munge_cred_t c) assert (c->mac_len <= sizeof (c->mac)); memset (c->mac, 0, c->mac_len); + conf_realm_t realm = get_realm (conf, m->realm_str); + if (!realm) + goto err_realm; + /* Compute MAC. */ - if (mac_init (&x, m->mac, conf->mac_key, conf->mac_key_len) < 0) { + if (mac_init (&x, m->mac, realm->mac_key, realm->mac_key_len) < 0) { goto err; } if (mac_update (&x, c->outer, c->outer_len) < 0) { @@ -563,6 +567,9 @@ enc_mac (munge_cred_t c) err: return (m_msg_set_err (m, EMUNGE_SNAFU, strdup ("Failed to MAC credential"))); +err_realm: + return (m_msg_set_err (m, EMUNGE_BAD_REALM, + strdup ("Unknown realm"))); } @@ -584,6 +591,9 @@ enc_encrypt (munge_cred_t c) if (m->cipher == MUNGE_CIPHER_NONE) { return (0); } + + conf_realm_t realm = get_realm (conf, m->realm_str); + /* Compute DEK. * msg-dek = MAC (msg-mac) using DEK subkey */ @@ -596,7 +606,7 @@ enc_encrypt (munge_cred_t c) assert (c->dek_len <= sizeof (c->dek)); n = c->dek_len; - if (mac_block (m->mac, conf->dek_key, conf->dek_key_len, + if (mac_block (m->mac, realm->dek_key, realm->dek_key_len, c->dek, &n, c->mac, c->mac_len) < 0) { return (m_msg_set_err (m, EMUNGE_SNAFU, strdup ("Failed to compute DEK"))); diff --git a/src/munged/munged.8.in b/src/munged/munged.8.in index 9770caec..bca6a9c8 100644 --- a/src/munged/munged.8.in +++ b/src/munged/munged.8.in @@ -38,10 +38,11 @@ munged \- MUNGE daemon The \fBmunged\fR daemon is responsible for authenticating local MUNGE clients and servicing their credential encode & decode requests. .PP -All \fBmunged\fR daemons within a security realm share a common key. -All hosts within this realm are expected to have common users/UIDs and -groups/GIDs. The key is used to cryptographically protect the credentials; -it is created with the \fBmungekey\fR command. +All \fBmunged\fR daemons within a security domain share common keys for +configured realms. All hosts within this domain are expected to have +common users/UIDs and groups/GIDs. The keys are used to cryptographically +validate the authenticity of credentials; they are created with the +\fBmungekey\fR command. .PP When a credential is created, \fBmunged\fR embeds metadata within it including the effective UID and GID of the requesting client (as determined @@ -129,7 +130,15 @@ A value of 0 causes it to be computed initially but never updated (unless triggered by a \fBSIGHUP\fR). A value of \-1 causes it to be disabled. .TP .BI "\-\-key\-file " path -Specify an alternate pathname to the key file. +Specify pathname to the default realm's key file. +.TP +.BI "\-\-keydir " path +Specify pathname to directory containing per-realm key files. +.TP +.BI "\-\-realm " realm +Enable service for the given realm in addition to the default +realm. Per-realm key file path is constructed from preceeding --keyfile +option. .TP .BI "\-\-log\-file " path Specify an alternate pathname to the log file. @@ -180,12 +189,12 @@ Terminate the daemon. .\" .SH FILES .SH NOTES -All clocks within a security realm must be kept in sync within the credential -time-to-live setting. +All clocks within a security domain must be kept in sync within the +credential time-to-live setting. .PP While \fBmunged\fR prevents a given credential from being decoded on a particular host more than once, nothing prevents a credential from being -decoded on multiple hosts within the security realm before it expires. +decoded on multiple hosts within the security domain before it expires. .SH AUTHOR Chris Dunlap diff --git a/src/munged/munged.c b/src/munged/munged.c index 96b368cf..c82cc4f8 100644 --- a/src/munged/munged.c +++ b/src/munged/munged.c @@ -143,7 +143,7 @@ main (int argc, char *argv[]) conf->seed_name = NULL; } } - create_subkeys (conf); + create_subkeys (conf, get_realm(conf, "")); conf->gids = gids_create (conf->gids_update_secs, conf->got_group_stat); replay_init (); timer_init (); diff --git a/src/mungekey/mungekey.8.in b/src/mungekey/mungekey.8.in index d8845160..365ae404 100644 --- a/src/mungekey/mungekey.8.in +++ b/src/mungekey/mungekey.8.in @@ -33,6 +33,7 @@ mungekey \- MUNGE key management utility .SH SYNOPSIS .B mungekey [\fB\-c\fR] [\fB\-b\fR \fIbits\fR] [\fB\-f\fR] [\fB\-k\fR \fIkeyfile\fR] +[\fB\-K\fR \fIkeydir\fR] [\fB\-r\fR \fIrealm\fR] [\fB\-v\fR] .br @@ -41,12 +42,13 @@ The \fBmungekey\fR executable is the key management utility for MUNGE. It should be run by the same user that starts the \fBmunged\fR daemon. .PP If no options are specified, \fBmungekey\fR will attempt to create a new -key using the default settings; this will fail if the keyfile already exists. +key using the default settings; this will fail if the default \fIrealm\fR's +keyfile already exists. .PP -All \fBmunged\fR daemons within a security realm must use the same key. -In other words, all hosts within an administrative group (or cluster) -using MUNGE for authentication must use the same key; this keyfile can be -created on one host and then securely copied to all other hosts. +All hosts using MUNGE for authentication within an security domain must use +the same shared symmetric key for each \fIrealm\fR each host should have +access to; these keyfiles should be created on one host and then securely +copied to other hosts. .SH OPTIONS .TP @@ -63,7 +65,13 @@ Force the keyfile to be overwritten if it already exists. Display a summary of the command-line options. .TP .BI "\-k, \-\-keyfile " path -Specify the keyfile pathname. +Set keyfile to create. This can be overriden by \fB\-\-realm\fR. +.TP +.BI "\-K, \-\-keydir " path +Directory for per-realm key files. +.TP +.BI "\-r, \-\-realm " realm +Set keyfile to create based on \fB\-\-keydir\fR path and \fIrealm\fR name. .TP .BI "\-L, \-\-license" Display license information. diff --git a/tests/0012-munge-cmdline.t b/tests/0012-munge-cmdline.t index 07f50751..bb51c022 100755 --- a/tests/0012-munge-cmdline.t +++ b/tests/0012-munge-cmdline.t @@ -612,6 +612,13 @@ test_expect_success 'munge --ttl for invalid negative number' ' test_must_fail "${MUNGE}" --socket="${MUNGE_SOCKET}" --no-input --ttl=-2 ' +test_expect_success 'munge --realm roundtrip' ' + "${MUNGE}" --socket="${MUNGE_SOCKET}" --no-input --realm=winterfell | \ + "${UNMUNGE}" --socket="${MUNGE_SOCKET}" --key REALM | \ + grep -q "^REALM: *winterfell" +' + + test_expect_success 'stop munged' ' munged_stop '