aclproxy.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright 2001 Sun Microsystems, Inc.
  3. * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. #include "acl.h"
  7. #define BEGIN do {
  8. #define END } while(0);
  9. /* ------------------------------------------------------------
  10. * LDAPProxyAuth
  11. *
  12. * ProxyAuthControl ::= SEQUENCE {
  13. * authorizationDN LDAPDN
  14. * }
  15. */
  16. struct LDAPProxyAuth
  17. {
  18. char *auth_dn;
  19. };
  20. typedef struct LDAPProxyAuth LDAPProxyAuth;
  21. /*
  22. * delete_LDAPProxyAuth
  23. */
  24. static void
  25. delete_LDAPProxyAuth(LDAPProxyAuth *spec)
  26. {
  27. if (!spec) return;
  28. slapi_ch_free((void**)&spec->auth_dn);
  29. slapi_ch_free((void**)&spec);
  30. }
  31. /*
  32. * parse_LDAPProxyAuth
  33. *
  34. * Parse a BER encoded value into the compoents of the LDAP ProxyAuth control.
  35. * The 'version' parameter should be 1 or 2.
  36. *
  37. * Returns an LDAP error code (LDAP_SUCCESS if all goes well) and sets
  38. * *errtextp if appropriate.
  39. */
  40. static int
  41. parse_LDAPProxyAuth(struct berval *spec_ber, int version, char **errtextp,
  42. LDAPProxyAuth **out)
  43. {
  44. int lderr = LDAP_OPERATIONS_ERROR; /* pessimistic */
  45. LDAPProxyAuth *spec = NULL;
  46. BerElement *ber = NULL;
  47. char *errstring = "unable to parse proxied authorization control";
  48. BEGIN
  49. unsigned long tag;
  50. if ( version != 1 && version != 2 ) {
  51. break;
  52. }
  53. /* create_LDAPProxyAuth */
  54. spec = (LDAPProxyAuth*)slapi_ch_calloc(1,sizeof (LDAPProxyAuth));
  55. if (!spec) {
  56. break;
  57. }
  58. ber = ber_init(spec_ber);
  59. if (!ber) {
  60. break;
  61. }
  62. if ( version == 1 ) {
  63. tag = ber_scanf(ber, "{a}", &spec->auth_dn);
  64. } else {
  65. tag = ber_scanf(ber, "a", &spec->auth_dn);
  66. }
  67. if (tag == LBER_ERROR) {
  68. lderr = LDAP_PROTOCOL_ERROR;
  69. break;
  70. }
  71. /*
  72. * In version 2 of the control, the control value is actually an
  73. * authorization ID (see section 9 of RFC 2829). We only support
  74. * the "dnAuthzId" flavor, which looks like "dn:<DN>" where <DN> is
  75. * an actual DN, e.g., "dn:uid=bjensen,dc=example,dc=com". So we
  76. * need to strip off the dn: if present and reject the operation if
  77. * not.
  78. */
  79. if (2 == version) {
  80. if ( NULL == spec->auth_dn || strlen( spec->auth_dn ) < 3 ||
  81. strncmp( "dn:", spec->auth_dn, 3 ) != 0 ) {
  82. lderr = LDAP_INSUFFICIENT_ACCESS; /* per Proxied Auth. I-D */
  83. errstring = "proxied authorization id must be a DN (dn:...)";
  84. break;
  85. }
  86. strcpy( spec->auth_dn, spec->auth_dn + 3 );
  87. }
  88. slapi_dn_normalize(spec->auth_dn);
  89. lderr = LDAP_SUCCESS; /* got it! */
  90. END
  91. /* Cleanup */
  92. if (ber) ber_free(ber, 0);
  93. if ( LDAP_SUCCESS != lderr)
  94. {
  95. if (spec) delete_LDAPProxyAuth(spec);
  96. spec = 0;
  97. if ( NULL != errtextp ) {
  98. *errtextp = errstring;
  99. }
  100. }
  101. *out = spec;
  102. return lderr;
  103. }
  104. /*
  105. * proxyauth_dn - find the users DN in the proxyauth control if it is
  106. * present. The return value has been malloced for you.
  107. *
  108. * Returns an LDAP error code. If anything than LDAP_SUCCESS is returned,
  109. * the error should be returned to the client. LDAP_SUCCESS is always
  110. * returned if the proxy auth control is not present or not critical.
  111. */
  112. int
  113. acl_get_proxyauth_dn( Slapi_PBlock *pb, char **proxydnp, char **errtextp )
  114. {
  115. char *dn = 0;
  116. LDAPProxyAuth *spec = 0;
  117. int rv, lderr = LDAP_SUCCESS; /* optimistic */
  118. BEGIN
  119. struct berval *spec_ber;
  120. LDAPControl **controls;
  121. int present;
  122. int critical;
  123. int version = 1;
  124. rv = slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
  125. if (rv) break;
  126. present = slapi_control_present( controls, LDAP_CONTROL_PROXYAUTH,
  127. &spec_ber, &critical );
  128. if (!present) {
  129. present = slapi_control_present( controls, LDAP_CONTROL_PROXIEDAUTH,
  130. &spec_ber, &critical );
  131. if (!present) break;
  132. version = 2;
  133. /*
  134. * Note the according to the Proxied Authorization I-D, the
  135. * control is always supposed to be marked critical by the
  136. * client. If it is not, we return a protocolError.
  137. */
  138. if ( !critical ) {
  139. lderr = LDAP_PROTOCOL_ERROR;
  140. if ( NULL != errtextp ) {
  141. *errtextp = "proxy control must be marked critical";
  142. }
  143. break;
  144. }
  145. }
  146. rv = parse_LDAPProxyAuth(spec_ber, version, errtextp, &spec);
  147. if (LDAP_SUCCESS != rv) {
  148. if ( critical ) {
  149. lderr = rv;
  150. }
  151. break;
  152. }
  153. dn = slapi_ch_strdup(spec->auth_dn);
  154. if (slapi_dn_isroot(dn) ) {
  155. lderr = LDAP_UNWILLING_TO_PERFORM;
  156. *errtextp = "Proxy dn should not be rootdn";
  157. break;
  158. }
  159. END
  160. if (spec) delete_LDAPProxyAuth(spec);
  161. if ( NULL != proxydnp ) {
  162. *proxydnp = dn;
  163. } else {
  164. slapi_ch_free( (void **)&dn );
  165. }
  166. return lderr;
  167. }