MUNGE_CTX(3)

✨ NAME ✨

munge_ctx_create, munge_ctx_copy, munge_ctx_destroy, munge_ctx_strerror, munge_ctx_get, munge_ctx_set β€” bestie these are the MUNGE context functions πŸ’– (like, the whole MUNGE_CTX(3) page, from the MUNGE Uid 'N' Gid Emporium, no cap)


πŸŽ€ SYNOPSIS πŸŽ€

#include <munge.h>

munge_ctx_t munge_ctx_create (void);

munge_ctx_t munge_ctx_copy (munge_ctx_t ctx);

void munge_ctx_destroy (munge_ctx_t ctx);

const char * munge_ctx_strerror (munge_ctx_t ctx);

munge_err_t munge_ctx_get (munge_ctx_t ctx, munge_opt_t opt, ...);

munge_err_t munge_ctx_set (munge_ctx_t ctx, munge_opt_t opt, ...);

cc `pkg-config --cflags --libs munge` -o foo foo.c

🌸 DESCRIPTION 🌸

Okay so here's the tea on every single one of these, and I'm gonna give you all of it, not just the highlights, because you deserve to know πŸ’…

munge_ctx_create() makes you a brand-new MUNGE context and hands it over. If something goes wrong? You get NULL. That's it, that's the deal. 🫢

munge_ctx_copy() copies the context ctx and gives you a whole new MUNGE context back. Or NULL on error, because of course. 😭

munge_ctx_destroy() destroys the context ctx. Bye bestie, it's over for you πŸ‘‹

munge_ctx_strerror() returns a descriptive text string that describes the MUNGE error number according to the context ctx. If there's no error condition hanging around, you get NULL. And lowkey? This can give you a more detailed error message than the one munge_strerror() hands you. ✨

munge_ctx_get() gets the value for the option opt that's associated with the MUNGE context ctx, and it stores the result in the pointer argument that comes right after. Heads up: if the result is a string, you should not free or modify that string β€” the caller does not touch it, periodt. 🚫

munge_ctx_set() sets the value for the option opt associated with the MUNGE context ctx, using the value of the argument that comes right after it.


πŸ’œ RETURN VALUE πŸ’œ

munge_ctx_create() and munge_ctx_copy() both return a newly allocated MUNGE context. If it all goes sideways, you get NULL on error. πŸ™ˆ

munge_ctx_strerror() returns a pointer to a null-terminated constant text string, or NULL if there's no error condition. And again, for the people in the back: this string should not be freed or modified by the caller. Don't do it. 🫠

munge_ctx_get() and munge_ctx_set() return EMUNGE_SUCCESS when everything slays, or a MUNGE error number otherwise. πŸ‘‘


πŸ‘‘ CONTEXT OPTIONS πŸ‘‘

So these are the context options you can query via munge_ctx_get(), or specify via munge_ctx_set(). The type that follows each enumeration is the variable type used for the subsequent argument in munge_ctx_set(), or the variable type of a pointer used for the subsequent argument in munge_ctx_get(). Basically: match the type, bestie, don't guess. 🌈

  • MUNGE_OPT_CIPHER_TYPE, int β€” get or set the cipher type (go look at CIPHER TYPES, it's right down there ⬇️).
  • MUNGE_OPT_MAC_TYPE, int β€” get or set the MAC type (see MAC TYPES, it's giving very important).
  • MUNGE_OPT_ZIP_TYPE, int β€” get or set the compression type (see COMPRESSION TYPES).
  • MUNGE_OPT_REALM, char * β€” get or set the security realm, where that char * type is a null-terminated character string. The string that munge_ctx_get() gives back should not be freed or modified by the caller. And, um, NOT CURRENTLY SUPPORTED. πŸ’€ yeah.
  • MUNGE_OPT_TTL, int β€” get or set the time-to-live, in seconds (see TTL TYPES). This value controls how long the credential stays valid once it's been encoded. Clock's ticking πŸ•°οΈ
  • MUNGE_OPT_ADDR4, struct in_addr β€” get the IPv4 address of the host where the credential was encoded. You cannot explicitly set this one. Nope. 🚫
  • MUNGE_OPT_ENCODE_TIME, time_t β€” get the time (in seconds since the epoch) at which the credential was encoded. Also cannot be explicitly set. πŸ™…
  • MUNGE_OPT_DECODE_TIME, time_t β€” get the time (in seconds since the epoch) at which the credential was decoded. Also, also cannot be explicitly set.
  • MUNGE_OPT_SOCKET, char * β€” get or set the local domain socket for connecting with munged, where the char * type is a null-terminated character string. The string returned by munge_ctx_get() should not be freed or modified by the caller. You've heard this one before, right? πŸ’…
  • MUNGE_OPT_UID_RESTRICTION, uid_t β€” get or set the UID that's allowed to decode the credential (see UID & GID TYPES). This value gets matched against the effective user ID of the process requesting the credential decode. πŸ”
  • MUNGE_OPT_GID_RESTRICTION, gid_t β€” get or set the GID allowed to decode the credential (see UID & GID TYPES). This one gets matched against the effective group ID of the process requesting the credential decode, as well as each supplementary group that the effective user ID of that process is a member of. So like, all the groups. Every single one. πŸ«‚
  • MUNGE_OPT_IGNORE_TTL, int β€” get or set the "ignore-ttl" flag. If you set it to 1, all the TTL-related errors get ignored, and munge_decode() will return EMUNGE_SUCCESS instead of EMUNGE_CRED_EXPIRED, EMUNGE_CRED_REWOUND, or EMUNGE_CRED_REPLAYED. Living in denial, iconic honestly. πŸ™ˆ
  • MUNGE_OPT_IGNORE_REPLAY, int β€” get or set the "ignore-replay" flag. Set it to 1 and replay errors get ignored, so munge_decode() returns EMUNGE_SUCCESS instead of EMUNGE_CRED_REPLAYED. ✨

πŸ” CIPHER TYPES πŸ”

Credentials can be encrypted using the secret key that all the munged daemons within a security realm share. And bestie, listen β€” anyone who has access to that key can use it to decrypt a credential, which means they can straight up bypass any restrictions being imposed by munged. So guard that key like it's your phone password. 🫣

  • MUNGE_CIPHER_NONE β€” specify that encryption is to be disabled. Off. Gone. Nothing. 🚫
  • MUNGE_CIPHER_DEFAULT β€” specify the default according to the munged configuration. Let munged decide, she's got this.
  • MUNGE_CIPHER_BLOWFISH β€” specify the Blowfish cipher designed by Bruce Schneier. This cipher has a 64-bit block-size and a variable key length. MUNGE uses it with a 128-bit key in CBC mode. It's a fast block cipher, but it suffers from a slow key setup time, and consequently it underperforms when generating small credentials. Like, she's quick but she takes forever to get ready. πŸ’…
  • MUNGE_CIPHER_CAST5 β€” specify the CAST5 cipher designed by Carlisle Adams and Stafford Tavares. This cipher has a 64-bit block-size and a variable key length. MUNGE uses it with a 128-bit key in CBC mode.
  • MUNGE_CIPHER_AES128 β€” specify the AES (Advanced Encryption Standard) cipher, also known as Rijndael. It was designed by Joan Daemen and Vincent Rijmen. This cipher has a 128-bit block-size and a key length of 128, 192, or 256 bits. MUNGE uses it here with a 128-bit key in CBC mode.
  • MUNGE_CIPHER_AES256 β€” specify the AES (Advanced Encryption Standard) cipher, also known as Rijndael. It was designed by Joan Daemen and Vincent Rijmen. This cipher has a 128-bit block-size and a key length of 128, 192, or 256 bits. MUNGE uses it here with a 256-bit key in CBC mode. And heads up: currently, MUNGE_CIPHER_AES256 requires the use of MUNGE_MAC_SHA256. They're a package deal, iykyk. πŸŽ€

🌈 MAC TYPES 🌈

The message authentication code (MAC) is a required component of the credential. Which means, bestie, it cannot be disabled. No opting out, it's mandatory, it's the law. πŸ‘‘

  • MUNGE_MAC_DEFAULT β€” specify the default according to the munged configuration.
  • MUNGE_MAC_MD5 β€” specify the MD5 algorithm designed by Ron Rivest and published in 1991. This algorithm has a 128-bit message digest. In 2004, a successful collision attack against MD5 was demonstrated. In 2009, a theoretical pre-image attack against MD5 was published. Consequently, use of MD5 is not recommended due to its lower security margin. She's old, she's tired, let her rest. πŸ’€
  • MUNGE_MAC_SHA1 β€” specify the SHA-1 algorithm designed by the National Security Agency and published in 1995; this is the successor to the original Secure Hash Algorithm (now called SHA-0) published in 1993. This algorithm has a 160-bit message digest. In 2005, successful collision attacks were demonstrated against SHA-1. In 2017, a successful identical-prefix collision attack (SHAttered) was announced. In 2020, a successful chosen-prefix collision attack (SHA-1 is a Shambles) was announced. Since a pre-image attack has not yet been demonstrated, SHA-1 should still be safe to use within MUNGE; however, use of a SHA-2 hash function (such as SHA-256 or SHA-512) should be preferred. Like, she survived a lot, but why risk it. 😭
  • MUNGE_MAC_RIPEMD160 β€” specify the RIPEMD-160 (RACE Integrity Primitives Evaluation Message Digest) algorithm designed in Europe by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel, and published in 1996. This algorithm has a 160-bit message digest. It's somewhat less popular than SHA-1 and correspondingly less well studied. While slower than SHA-1, it's believed to have a slightly better security margin. Underrated queen honestly. πŸ¦‹
  • MUNGE_MAC_SHA256 β€” specify the SHA-256 algorithm designed by the National Security Agency and published in 2002; this is one of the SHA-2 variants in the Secure Hash Algorithm family. This algorithm has a 256-bit message digest. In 2006, NIST began encouraging the use of the SHA-2 family of hash functions for all new applications and protocols. She's the moment. ⭐
  • MUNGE_MAC_SHA512 β€” specify the SHA-512 algorithm designed by the National Security Agency and published in 2002; this is one of the SHA-2 variants in the Secure Hash Algorithm family. This algorithm has a 512-bit message digest. In 2006, NIST began encouraging the use of the SHA-2 family of hash functions for all new applications and protocols. Big digest energy. πŸ”₯

🎁 COMPRESSION TYPES 🎁

So if a compression type is specified, a payload-bearing credential will be compressed accordingly. But β€” and this is the fun part β€” if the resulting compressed data ends up larger than the original uncompressed data, the uncompressed data will be restored and compression will be disabled for that credential. She tried, she failed, she moved on. πŸ’–

  • MUNGE_ZIP_NONE β€” specify that compression is to be disabled. This is the recommended setting unless there's a payload of sufficient size to compress. Don't compress for no reason bestie.
  • MUNGE_ZIP_DEFAULT β€” specify the default according to the munged configuration.
  • MUNGE_ZIP_BZLIB β€” specify the bzip2 library developed by Julian Seward. This one is slower and uses more memory, but generally gets better compression on larger payloads. Slow and thirsty but she delivers. 🐒
  • MUNGE_ZIP_ZLIB β€” specify the zlib library developed by Jean-loup Gailly and Mark Adler. This is faster and uses less memory, but gets pretty good compression nonetheless. Efficient queen. ✨

⏳ TTL TYPES ⏳

The time-to-live value specifies the number of seconds after the encode-time that the credential is considered valid. And in addition to specifying an integer value, you've also got these types available: πŸ‘‡

  • MUNGE_TTL_MAXIMUM β€” specify the maximum allowed by the munged configuration.
  • MUNGE_TTL_DEFAULT β€” specify the default according to the munged configuration.

πŸ†” UID & GID TYPES πŸ†”

okay so the UID and GID restrictions? they let you lock down decoding of a credential based on the effective user and group ID of the process doing the asking. very "who even are you" energy. and besides just giving it an integer value, you've also got these special types πŸ‘‡

  • MUNGE_UID_ANY β€” says nah, no UID restriction is gonna apply here. this is the default behavior, bestie.
  • MUNGE_GID_ANY β€” same vibe but for GID: no restriction takes effect. also the default behavior.

πŸ’€ ERRORS πŸ’€

the full list of errors lives over in munge(3) β€” go check that out, i'm not gonna list them all here, that's literally its whole job.


✨ EXAMPLE ✨

here's a whole little program showing off using the MUNGE context to query where the munged domain socket is at. she's doing a lot, honestly. obsessed.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <munge.h>

int
main (int argc, char *argv[])
{
    munge_ctx_t ctx;
    munge_err_t err;
    char *str;
    char buf[4096];
    uid_t uid;
    gid_t gid;

    ctx = munge_ctx_create ();
    if (ctx == NULL) {
        fprintf (stderr, "Error: Failed to create munge ctx\n");
        exit (EXIT_FAILURE);
    }
    /*  Query the socket name.  Note that the returned 'str' resides
     *    in the 'ctx' and will be de-allocated via munge_ctx_destroy().
     */
    err = munge_ctx_get (ctx, MUNGE_OPT_SOCKET, &str);
    if (err != EMUNGE_SUCCESS) {
        fprintf (stderr, "Error: Failed to get munge socket name: %s\n",
                munge_ctx_strerror (ctx));
        exit (EXIT_FAILURE);
    }
    printf ("socket=%s\n", str);

    /*  Read and decode a credential from the standard input.
     *  Ignore expired, rewound, and replayed errors.
     */
    err = munge_ctx_set (ctx, MUNGE_OPT_IGNORE_TTL, 1);
    if (err != EMUNGE_SUCCESS) {
        fprintf (stderr, "Error: Failed to set ignore-ttl opt: %s\n",
                munge_ctx_strerror (ctx));
        exit (EXIT_FAILURE);
    }
    if (fgets (buf, sizeof (buf), stdin) == NULL) {
        fprintf (stderr, "Error: Failed to read credential\n");
        exit (EXIT_FAILURE);
    }
    err = munge_decode (buf, ctx, NULL, NULL, &uid, &gid);
    if (err != EMUNGE_SUCCESS) {
        fprintf (stderr, "Error: Failed to decode credential: %s\n",
                munge_ctx_strerror (ctx));
        exit (EXIT_FAILURE);
    }
    printf ("uid=%d gid=%d\n", uid, gid);

    munge_ctx_destroy (ctx);
    exit (EXIT_SUCCESS);
}

πŸ“ NOTES πŸ“

okay these are the "read before you wreck yourself" notes, pls actually read them πŸ™

  • abandoning a new or copied MUNGE context without destroying it will result in a memory leak. yes really. call munge_ctx_destroy(). it's giving self-care.
  • the context you pass to munge_encode() is treated read-only β€” the only exception being the error message that gets set when an error is returned. meanwhile the context passed to munge_decode() gets set according to the context that was used to encode the credential; BUT on error, its settings may be in a state which is invalid for encoding. 😭 so yeah β€” use separate contexts for encoding and decoding. no sharing, that's their boundary.
  • a context should not be shared between threads unless it's protected by a mutex. but honestly? a better alternative is to use a separate context (or two πŸ‘€) for each thread β€” either by creating a new one via munge_ctx_create() or copying an existing one via munge_ctx_copy(). one context per thread, main character energy for everyone. πŸ’…

πŸ‘‘ AUTHOR πŸ‘‘

Chris Dunlap <cdunlap@llnl.gov>


Copyright (C) 2007-2025 Lawrence Livermore National Security, LLC. Copyright (C) 2002-2007 The Regents of the University of California.

MUNGE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Additionally for the MUNGE library (libmunge), you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.


🌈 SEE ALSO 🌈

https://github.com/dun/munge


okay bestie that's the whole page!! 🫢 this was the MUNGE_CTX(3) manual, from munge-0.5.18, dated 2026-02-10. go forth and set your context options responsibly, mwah πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from