/crypto/heimdal/lib/gssapi/krb5/add_cred.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 239 lines · 170 code · 34 blank · 35 comment · 51 complexity · b251f27d847112d99156181b0c9a9777 MD5 · raw file

  1. /*
  2. * Copyright (c) 2003 Kungliga Tekniska Hรถgskolan
  3. * (Royal Institute of Technology, Stockholm, Sweden).
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. *
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * 3. Neither the name of the Institute nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "gsskrb5_locl.h"
  34. OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred (
  35. OM_uint32 *minor_status,
  36. const gss_cred_id_t input_cred_handle,
  37. const gss_name_t desired_name,
  38. const gss_OID desired_mech,
  39. gss_cred_usage_t cred_usage,
  40. OM_uint32 initiator_time_req,
  41. OM_uint32 acceptor_time_req,
  42. gss_cred_id_t *output_cred_handle,
  43. gss_OID_set *actual_mechs,
  44. OM_uint32 *initiator_time_rec,
  45. OM_uint32 *acceptor_time_rec)
  46. {
  47. krb5_context context;
  48. OM_uint32 ret, lifetime;
  49. gsskrb5_cred cred, handle;
  50. krb5_const_principal dname;
  51. handle = NULL;
  52. cred = (gsskrb5_cred)input_cred_handle;
  53. dname = (krb5_const_principal)desired_name;
  54. GSSAPI_KRB5_INIT (&context);
  55. if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) {
  56. *minor_status = 0;
  57. return GSS_S_BAD_MECH;
  58. }
  59. if (cred == NULL && output_cred_handle == NULL) {
  60. *minor_status = 0;
  61. return GSS_S_NO_CRED;
  62. }
  63. if (cred == NULL) { /* XXX standard conformance failure */
  64. *minor_status = 0;
  65. return GSS_S_NO_CRED;
  66. }
  67. /* check if requested output usage is compatible with output usage */
  68. if (output_cred_handle != NULL) {
  69. HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
  70. if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) {
  71. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  72. *minor_status = GSS_KRB5_S_G_BAD_USAGE;
  73. return(GSS_S_FAILURE);
  74. }
  75. }
  76. /* check that we have the same name */
  77. if (dname != NULL &&
  78. krb5_principal_compare(context, dname,
  79. cred->principal) != FALSE) {
  80. if (output_cred_handle)
  81. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  82. *minor_status = 0;
  83. return GSS_S_BAD_NAME;
  84. }
  85. /* make a copy */
  86. if (output_cred_handle) {
  87. krb5_error_code kret;
  88. handle = calloc(1, sizeof(*handle));
  89. if (handle == NULL) {
  90. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  91. *minor_status = ENOMEM;
  92. return (GSS_S_FAILURE);
  93. }
  94. handle->usage = cred_usage;
  95. handle->lifetime = cred->lifetime;
  96. handle->principal = NULL;
  97. handle->keytab = NULL;
  98. handle->ccache = NULL;
  99. handle->mechanisms = NULL;
  100. HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
  101. ret = GSS_S_FAILURE;
  102. kret = krb5_copy_principal(context, cred->principal,
  103. &handle->principal);
  104. if (kret) {
  105. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  106. free(handle);
  107. *minor_status = kret;
  108. return GSS_S_FAILURE;
  109. }
  110. if (cred->keytab) {
  111. char *name = NULL;
  112. ret = GSS_S_FAILURE;
  113. kret = krb5_kt_get_full_name(context, cred->keytab, &name);
  114. if (kret) {
  115. *minor_status = kret;
  116. goto failure;
  117. }
  118. kret = krb5_kt_resolve(context, name,
  119. &handle->keytab);
  120. krb5_xfree(name);
  121. if (kret){
  122. *minor_status = kret;
  123. goto failure;
  124. }
  125. }
  126. if (cred->ccache) {
  127. const char *type, *name;
  128. char *type_name = NULL;
  129. ret = GSS_S_FAILURE;
  130. type = krb5_cc_get_type(context, cred->ccache);
  131. if (type == NULL){
  132. *minor_status = ENOMEM;
  133. goto failure;
  134. }
  135. if (strcmp(type, "MEMORY") == 0) {
  136. ret = krb5_cc_new_unique(context, type,
  137. NULL, &handle->ccache);
  138. if (ret) {
  139. *minor_status = ret;
  140. goto failure;
  141. }
  142. ret = krb5_cc_copy_cache(context, cred->ccache,
  143. handle->ccache);
  144. if (ret) {
  145. *minor_status = ret;
  146. goto failure;
  147. }
  148. } else {
  149. name = krb5_cc_get_name(context, cred->ccache);
  150. if (name == NULL) {
  151. *minor_status = ENOMEM;
  152. goto failure;
  153. }
  154. kret = asprintf(&type_name, "%s:%s", type, name);
  155. if (kret < 0 || type_name == NULL) {
  156. *minor_status = ENOMEM;
  157. goto failure;
  158. }
  159. kret = krb5_cc_resolve(context, type_name,
  160. &handle->ccache);
  161. free(type_name);
  162. if (kret) {
  163. *minor_status = kret;
  164. goto failure;
  165. }
  166. }
  167. }
  168. ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
  169. if (ret)
  170. goto failure;
  171. ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
  172. &handle->mechanisms);
  173. if (ret)
  174. goto failure;
  175. }
  176. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  177. ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred,
  178. NULL, &lifetime, NULL, actual_mechs);
  179. if (ret)
  180. goto failure;
  181. if (initiator_time_rec)
  182. *initiator_time_rec = lifetime;
  183. if (acceptor_time_rec)
  184. *acceptor_time_rec = lifetime;
  185. if (output_cred_handle) {
  186. *output_cred_handle = (gss_cred_id_t)handle;
  187. }
  188. *minor_status = 0;
  189. return ret;
  190. failure:
  191. if (handle) {
  192. if (handle->principal)
  193. krb5_free_principal(context, handle->principal);
  194. if (handle->keytab)
  195. krb5_kt_close(context, handle->keytab);
  196. if (handle->ccache)
  197. krb5_cc_destroy(context, handle->ccache);
  198. if (handle->mechanisms)
  199. gss_release_oid_set(NULL, &handle->mechanisms);
  200. free(handle);
  201. }
  202. if (output_cred_handle)
  203. HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
  204. return ret;
  205. }