Revert "Revert "oran-shell-release: release image for F""
[pti/rtp.git] / meta-starlingx / meta-stx-distro / recipes-security / gssproxy / files / Change-impersonator-check-code.patch
1 From 37d1667ad0cc91f46a493281e62775cc8bbe3b5b Mon Sep 17 00:00:00 2001
2 From: Simo Sorce <simo@redhat.com>
3 Date: Tue, 14 Mar 2017 10:20:08 -0400
4 Subject: [PATCH] Change impersonator check code
5
6 In MIT 1.15 we now have a native way to check for an impersonator,
7 implement the use of that function but still keep the fallback for
8 earlier krb5 versions that do not support this method for now.
9
10 Signed-off-by: Simo Sorce <simo@redhat.com>
11 Reviewed-by: Robbie Harwood <rharwood@redhat.com>
12 Merges: #172
13 (cherry picked from commit 73b50c0b2799f0aed53337a6516b8e1a27279ebf)
14 ---
15  proxy/configure.ac   |   3 +
16  proxy/src/gp_creds.c | 147 ++++++++++++++++++++++++++++++++-----------
17  2 files changed, 112 insertions(+), 38 deletions(-)
18
19 diff --git a/proxy/configure.ac b/proxy/configure.ac
20 index 63c0edf..c52dbb6 100644
21 --- a/proxy/configure.ac
22 +++ b/proxy/configure.ac
23 @@ -131,6 +131,9 @@ AC_CHECK_LIB(gssapi_krb5, gss_export_cred,,
24               [AC_MSG_ERROR([GSSAPI library does not support gss_export_cred])],
25               [$GSSAPI_LIBS])
26  
27 +AC_CHECK_DECLS([GSS_KRB5_GET_CRED_IMPERSONATOR], [], [],
28 +               [[#include <gssapi/gssapi_krb5.h>]])
29 +
30  AC_SUBST([KRB5_CFLAGS])
31  AC_SUBST([KRB5_LIBS])
32  AC_SUBST([GSSAPI_CFLAGS])
33 diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c
34 index 171a724..95a1c48 100644
35 --- a/proxy/src/gp_creds.c
36 +++ b/proxy/src/gp_creds.c
37 @@ -773,9 +773,9 @@ void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags)
38      *flags &= ~gpcall->service->filter_flags;
39  }
40  
41 -uint32_t gp_cred_allowed(uint32_t *min,
42 -                         struct gp_call_ctx *gpcall,
43 -                         gss_cred_id_t cred)
44 +
45 +static uint32_t get_impersonator_fallback(uint32_t *min, gss_cred_id_t cred,
46 +                                          char **impersonator)
47  {
48      uint32_t ret_maj = 0;
49      uint32_t ret_min = 0;
50 @@ -785,22 +785,6 @@ uint32_t gp_cred_allowed(uint32_t *min,
51      krb5_data config;
52      int err;
53  
54 -    if (cred == GSS_C_NO_CREDENTIAL) {
55 -        return GSS_S_CRED_UNAVAIL;
56 -    }
57 -
58 -    if (gpcall->service->trusted ||
59 -        gpcall->service->impersonate ||
60 -        gpcall->service->allow_const_deleg) {
61 -
62 -        GPDEBUGN(2, "Credentials allowed by configuration\n");
63 -        *min = 0;
64 -        return GSS_S_COMPLETE;
65 -    }
66 -
67 -    /* FIXME: krb5 specific code, should get an oid registerd to query the
68 -     * cred with gss_inquire_cred_by_oid() or similar instead */
69 -
70      err = krb5_init_context(&context);
71      if (err) {
72          ret_min = err;
73 @@ -835,21 +819,116 @@ uint32_t gp_cred_allowed(uint32_t *min,
74          goto done;
75      }
76  
77 +    err = krb5_cc_get_config(context, ccache, NULL, "proxy_impersonator",
78 +                             &config);
79 +    if (err == 0) {
80 +        *impersonator = strndup(config.data, config.length);
81 +        if (!*impersonator) {
82 +            ret_min = ENOMEM;
83 +            ret_maj = GSS_S_FAILURE;
84 +        } else {
85 +            ret_min = 0;
86 +            ret_maj = GSS_S_COMPLETE;
87 +        }
88 +        krb5_free_data_contents(context, &config);
89 +    } else {
90 +        ret_min = err;
91 +        ret_maj = GSS_S_FAILURE;
92 +    }
93 +
94 +done:
95 +    if (context) {
96 +        if (ccache) {
97 +            krb5_cc_destroy(context, ccache);
98 +        }
99 +        krb5_free_context(context);
100 +    }
101 +    free(memcache);
102 +
103 +    *min = ret_min;
104 +    return ret_maj;
105 +}
106 +
107 +#if !HAVE_DECL_GSS_KRB5_GET_CRED_IMPERSONATOR
108 +gss_OID_desc impersonator_oid = {
109 +    11, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e")
110 +};
111 +const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &impersonator_oid;
112 +#endif
113 +
114 +static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred,
115 +                                      char **impersonator)
116 +{
117 +    gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
118 +    uint32_t ret_maj = 0;
119 +    uint32_t ret_min = 0;
120 +    uint32_t discard;
121 +
122 +    *impersonator = NULL;
123 +
124 +    ret_maj = gss_inquire_cred_by_oid(&ret_min, cred,
125 +                                      GSS_KRB5_GET_CRED_IMPERSONATOR,
126 +                                      &bufset);
127 +    if (ret_maj == GSS_S_COMPLETE) {
128 +        if (bufset->count == 0) {
129 +            ret_min = ENOENT;
130 +            ret_maj = GSS_S_COMPLETE;
131 +            goto done;
132 +        }
133 +        *impersonator = strndup(bufset->elements[0].value,
134 +                                bufset->elements[0].length);
135 +        if (!*impersonator) {
136 +            ret_min = ENOMEM;
137 +            ret_maj = GSS_S_FAILURE;
138 +        }
139 +    } else if (ret_maj == GSS_S_UNAVAILABLE) {
140 +        /* Not supported by krb5 library yet, fallback to raw krb5 calls */
141 +        /* TODO: Remove once we set a required dependency on MIT 1.15+ */
142 +        ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator);
143 +        if (ret_maj == GSS_S_FAILURE) {
144 +            if (ret_min == KRB5_CC_NOTFOUND) {
145 +                ret_min = ENOENT;
146 +                ret_maj = GSS_S_COMPLETE;
147 +            }
148 +        }
149 +    }
150 +
151 +done:
152 +    (void)gss_release_buffer_set(&discard, &bufset);
153 +    *min = ret_min;
154 +    return ret_maj;
155 +}
156 +
157 +uint32_t gp_cred_allowed(uint32_t *min,
158 +                         struct gp_call_ctx *gpcall,
159 +                         gss_cred_id_t cred)
160 +{
161 +    char *impersonator = NULL;
162 +    uint32_t ret_maj = 0;
163 +    uint32_t ret_min = 0;
164 +
165 +    if (cred == GSS_C_NO_CREDENTIAL) {
166 +        return GSS_S_CRED_UNAVAIL;
167 +    }
168 +
169 +    if (gpcall->service->trusted ||
170 +        gpcall->service->impersonate ||
171 +        gpcall->service->allow_const_deleg) {
172 +
173 +        GPDEBUGN(2, "Credentials allowed by configuration\n");
174 +        *min = 0;
175 +        return GSS_S_COMPLETE;
176 +    }
177 +
178 +    ret_maj = get_impersonator_name(&ret_min, cred, &impersonator);
179 +    if (ret_maj) goto done;
180 +
181      /* if we find an impersonator entry we bail as that is not authorized,
182       * if it were then gpcall->service->allow_const_deleg would have caused
183       * the ealier check to return GSS_S_COMPLETE already */
184 -    err = krb5_cc_get_config(context, ccache, NULL, "proxy_impersonator",
185 -                             &config);
186 -    if (!err) {
187 -        krb5_free_data_contents(context, &config);
188 +    if (impersonator != NULL) {
189          ret_min = 0;
190          ret_maj = GSS_S_UNAUTHORIZED;
191 -    } else if (err != KRB5_CC_NOTFOUND) {
192 -        ret_min = err;
193 -        ret_maj = GSS_S_FAILURE;
194 -    } else {
195 -        ret_min = 0;
196 -        ret_maj = GSS_S_COMPLETE;
197      }
198  
199  done:
200 @@ -864,15 +943,7 @@ done:
201          GPDEBUG("Failure while checking credentials\n");
202          break;
203      }
204 -    if (context) {
205 -        /* NOTE: destroy only if we created a MEMORY ccache */
206 -        if (ccache) {
207 -            if (memcache) krb5_cc_destroy(context, ccache);
208 -            else krb5_cc_close(context, ccache);
209 -        }
210 -        krb5_free_context(context);
211 -    }
212 -    free(memcache);
213 +    free(impersonator);
214      *min = ret_min;
215      return ret_maj;
216  }