Coverage Report

Created: 2026-05-16 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gss-ntlmssp/src/gss_err.c
Line
Count
Source
1
/* Copyright (C) 2014 GSS-NTLMSSP contributors, see COPYING for license */
2
3
#include "config.h"
4
5
#include <stdlib.h>
6
#include <string.h>
7
#include <errno.h>
8
9
#include <gssapi/gssapi.h>
10
#include <gssapi/gssapi_ext.h>
11
12
#include "gss_ntlmssp.h"
13
14
#ifdef HAVE_NLS
15
#include <libintl.h>
16
0
#define _(s) dgettext(PACKAGE, (s))
17
#else
18
#define _(s) (s)
19
#endif
20
#define N_(s) s
21
22
/* the order is determined by ntlm_err_code order */
23
static const char *err_strs[] = {
24
                           N_("Unknown Error"),
25
    /* ERR_DECODE */       N_("Failed to decode data"),
26
    /* ERR_ENCODE */       N_("Failed to encode data"),
27
    /* ERR_CRYPTO */       N_("Crypto routine failure"),
28
    /* ERR_NOARG */        N_("A required argument is missing"),
29
    /* ERR_BADARG */       N_("Invalid value in argument"),
30
    /* ERR_NONAME */       N_("Name is empty"),
31
    /* ERR_NOSRVNAME */    N_("Not a server name"),
32
    /* ERR_NOUSRNAME */    N_("Not a user name"),
33
    /* ERR_BADLMLEVEL */   N_("Bad LM compatibility Level"),
34
    /* ERR_IMPOSSIBLE */   N_("An impossible error occurred"),
35
    /* ERR_BADCTX */       N_("Invalid or incomplete context"),
36
    /* ERR_WRONGCTX */     N_("Wrong context type"),
37
    /* ERR_WRONGMSG */     N_("Wrong message type"),
38
    /* ERR_REQNEGFLAG */   N_("A required Negotiate flag was not provided"),
39
    /* ERR_FAILNEGFLAGS */ N_("Failed to negotiate a common set of flags"),
40
    /* ERR_BADNEGFLAGS */  N_("Invalid combinations of negotiate flags"),
41
    /* ERR_NOSRVCRED */    N_("Not a server credential type"),
42
    /* ERR_NOUSRCRED */    N_("Not a user credential type"),
43
    /* ERR_BADCRED */      N_("Invalid or unknown credential"),
44
    /* ERR_NOTOKEN */      N_("Empty or missing token"),
45
    /* ERR_NOTSUPPORTED */ N_("Feature not supported"),
46
    /* ERR_NOTAVAIL */     N_("Feature not available"),
47
    /* ERR_NAMETOOLONG */  N_("Name is too long"),
48
    /* ERR_NOBINDINGS */   N_("Required channel bingings are not available"),
49
    /* ERR_TIMESKEW */     N_("Server and client clocks are too far apart"),
50
    /* ERR_EXPIRED */      N_("Expired"),
51
    /* ERR_KEYLEN */       N_("Invalid key length"),
52
    /* ERR_NONTLMV1 */     N_("NTLM version 1 not allowed"),
53
    /* ERR_NOUSRFOUND */   N_("User not found"),
54
};
55
56
#define UNKNOWN_ERROR err_strs[0]
57
58
uint32_t gssntlm_display_status(uint32_t *minor_status,
59
                                uint32_t status_value,
60
                                int status_type,
61
                                gss_OID mech_type,
62
                                uint32_t *message_context,
63
                                gss_buffer_t status_string)
64
0
{
65
0
    uint32_t retmaj;
66
0
    uint32_t retmin;
67
    /* if you can't say it in ~6 lines of text we don't bother */
68
0
    char buf[512];
69
0
    int err;
70
71
0
    if (!status_string) {
72
0
        return GSSERRS(ERR_NOARG, GSS_S_CALL_INACCESSIBLE_READ);
73
0
    }
74
75
0
    if (status_type != GSS_C_MECH_CODE) {
76
0
        return GSSERRS(ERR_BADARG, GSS_S_BAD_STATUS);
77
0
    }
78
79
0
    *minor_status = 0;
80
0
    *message_context = 0;
81
0
    status_string->length = 0;
82
0
    status_string->value = NULL;
83
84
0
    if (!status_value) {
85
        /* There must have been *some* error. No point saying 'Success' */
86
0
        goto done;
87
0
    }
88
89
0
    if (status_value > ERR_BASE && status_value < ERR_LAST) {
90
0
        status_string->value = strdup(_(err_strs[status_value - ERR_BASE]));
91
0
        if (!status_string->value) {
92
0
            return GSSERRS(ENOMEM, GSS_S_FAILURE);
93
0
        }
94
0
        goto done;
95
0
    }
96
97
    /* handle both XSI and GNU specific variants of strerror_r */
98
0
    errno = 0;
99
0
#if STRERROR_R_CHAR_P
100
0
    {
101
0
        char *ret;
102
0
        ret = strerror_r(status_value, buf, 400);
103
0
        if (ret == NULL) {
104
0
            err = errno;
105
0
        } else {
106
0
            if (ret != buf) {
107
0
                memmove(buf, ret, strlen(ret) + 1);
108
0
            }
109
0
            err = 0;
110
0
        }
111
0
    }
112
#else
113
    /* XSI version */
114
    err = strerror_r(status_value, buf, 400);
115
    /* The XSI-compliant strerror_r() function returns 0 on success.
116
     * On error, a (positive) error number is returned (since glibc
117
     * 2.13), or -1 is returned and errno is set to indicate the
118
     * error (glibc versions before 2.13). */
119
#endif
120
0
    if (err == -1) err = errno;
121
0
    switch (err) {
122
0
    case ERANGE:
123
        /* Screw it, they can have a truncated version */
124
0
    case 0:
125
0
        status_string->value = strdup(buf);
126
0
        break;
127
0
    default:
128
0
        break;
129
0
    }
130
131
0
done:
132
0
    if (!status_string->value) {
133
0
        status_string->value = strdup(_(UNKNOWN_ERROR));
134
0
        if (!status_string->value) {
135
0
            return GSSERRS(ENOMEM, GSS_S_FAILURE);
136
0
        }
137
0
    }
138
0
    status_string->length = strlen(status_string->value);
139
0
    return GSSERRS(0, GSS_S_COMPLETE);
140
0
}