summaryrefslogtreecommitdiff
path: root/plugin/error.c
blob: 29ee8068309c7db59062cffe0871a67f24437acc (plain)
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
/*
 * Store errors in the Kerberos context.
 *
 * Provides helper functions for the rest of the plugin code to store an error
 * message in the Kerberos context.
 *
 * Written by Russ Allbery <eagle@eyrie.org>
 * Copyright 2015 Russ Allbery <eagle@eyrie.org>
 * Copyright 2013
 *     The Board of Trustees of the Leland Stanford Junior University
 *
 * See LICENSE for licensing terms.
 */

#include <config.h>
#include <portable/kadmin.h>
#include <portable/krb5.h>
#include <portable/system.h>

#include <errno.h>
#include <ldap.h>

#include <plugin/internal.h>


/*
 * Internal helper function to set the Kerberos error message given a format,
 * an error code, and a variable argument structure.  Returns the error code
 * set, which is normally the same as the one passed in, but which may change
 * if we can't allocate memory.
 */
static krb5_error_code __attribute__((__format__(printf, 3, 0)))
set_error(krb5_context ctx, krb5_error_code code, const char *format,
          va_list args)
{
    char *message;

    if (vasprintf(&message, format, args) < 0)
        return sync_error_system(ctx, "cannot allocate memory");
    krb5_set_error_message(ctx, code, "%s", message);
    free(message);
    return code;
}


/*
 * Set the Kerberos error code to indicate a server configuration error and
 * set the message to the format and arguments passed to this function.
 */
krb5_error_code
sync_error_config(krb5_context ctx, const char *format, ...)
{
    va_list args;
    krb5_error_code code;

    va_start(args, format);
    code = set_error(ctx, KADM5_MISSING_KRB5_CONF_PARAMS, format, args);
    va_end(args);
    return code;
}


/*
 * Set the Kerberos error code to a generic kadmin failure error and the
 * message to the format and arguments passed to this function.  This is used
 * for internal failures of various types.
 */
krb5_error_code
sync_error_generic(krb5_context ctx, const char *format, ...)
{
    va_list args;
    krb5_error_code code;

    va_start(args, format);
    code = set_error(ctx, KADM5_FAILURE, format, args);
    va_end(args);
    return code;
}


/*
 * Set the Kerberos error code to a generic service unavailable error and the
 * message to the format and arguments passed to this function with the LDAP
 * error string appended.
 */
krb5_error_code
sync_error_ldap(krb5_context ctx, int code, const char *format, ...)
{
    va_list args;
    char *message;
    bool okay = true;
    int oerrno;

    va_start(args, format);
    if (vasprintf(&message, format, args) < 0) {
        oerrno = errno;
        krb5_set_error_message(ctx, errno, "cannot allocate memory: %s",
                               strerror(errno));
        okay = false;
    }
    va_end(args);
    if (!okay)
        return oerrno;
    krb5_set_error_message(ctx, KADM5_FAILURE, "%s: %s", message,
                           ldap_err2string(code));
    free(message);
    return KADM5_FAILURE;
}


/*
 * Set the Kerberos error code to the current errno and the message to the
 * format and arguments passed to this function.
 */
krb5_error_code
sync_error_system(krb5_context ctx, const char *format, ...)
{
    va_list args;
    char *message;
    bool okay = true;
    int oerrno = errno;

    va_start(args, format);
    if (vasprintf(&message, format, args) < 0) {
        oerrno = errno;
        krb5_set_error_message(ctx, errno, "cannot allocate memory: %s",
                               strerror(errno));
        okay = false;
    }
    va_end(args);
    if (!okay)
        return oerrno;
    krb5_set_error_message(ctx, oerrno, "%s: %s", message, strerror(oerrno));
    free(message);
    return oerrno;
}