]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/bind.c
67ce0fc16a8b894b74f88e9ac886334f243808c6
[openldap] / servers / slapd / back-ldap / bind.c
1 /* bind.c - ldap backend bind function */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7 /* This is an altered version */
8 /*
9  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
10  * 
11  * Permission is granted to anyone to use this software for any purpose
12  * on any computer system, and to alter it and redistribute it, subject
13  * to the following restrictions:
14  * 
15  * 1. The author is not responsible for the consequences of use of this
16  *    software, no matter how awful, even if they arise from flaws in it.
17  * 
18  * 2. The origin of this software must not be misrepresented, either by
19  *    explicit claim or by omission.  Since few users ever read sources,
20  *    credits should appear in the documentation.
21  * 
22  * 3. Altered versions must be plainly marked as such, and must not be
23  *    misrepresented as being the original software.  Since few users
24  *    ever read sources, credits should appear in the documentation.
25  * 
26  * 4. This notice may not be removed or altered.
27  */
28
29 #include "portable.h"
30
31 #include <stdio.h>
32
33 #include <ac/socket.h>
34 #include <ac/string.h>
35
36 #include "slap.h"
37 #include "back-ldap.h"
38
39 int
40 ldap_back_bind(
41     Backend             *be,
42     Connection          *conn,
43     Operation           *op,
44     const char          *dn,
45     const char          *ndn,
46     int                 method,
47     struct berval       *cred,
48         char            **edn
49 )
50 {
51         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
52         struct ldapconn *lc;
53
54         *edn = NULL;
55
56         lc = ldap_back_getconn(li, conn, op);
57         if (!lc)
58                 return( -1 );
59
60         if (ldap_bind_s(lc->ld, dn, cred->bv_val, method) != LDAP_SUCCESS)
61                 return( ldap_back_op_result(lc, op) );
62
63         lc->bound = 1;
64         return( 0 );
65 }
66
67 struct ldapconn *
68 ldap_back_getconn(struct ldapinfo *li, Connection *conn, Operation *op)
69 {
70         struct ldapconn *lc;
71         LDAP *ld;
72
73         ldap_pvt_thread_mutex_lock( &li->conn_mutex );
74         for (lc = li->lcs; lc; lc=lc->next)
75                 if (lc->conn == conn)
76                         break;
77         ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
78
79         /* Looks like we didn't get a bind. Open a new session... */
80         if (!lc) {
81                 int vers = conn->c_protocol;
82                 int err = ldap_initialize(&ld, li->url);
83                 if (err != LDAP_SUCCESS) {
84                         err = ldap_back_map_result(err);
85                         send_ldap_result( conn, op, err,
86                                 NULL, "ldap_init failed", NULL, NULL );
87                         return( NULL );
88                 }
89                 /* Set LDAP version. This will always succeed: If the client
90                  * bound with a particular version, then so can we.
91                  */
92                 ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &vers);
93
94                 lc = (struct ldapconn *)ch_malloc(sizeof(struct ldapconn));
95                 lc->conn = conn;
96                 lc->ld = ld;
97                 lc->bound = 0;
98                 ldap_pvt_thread_mutex_lock( &li->conn_mutex );
99                 lc->next = li->lcs;
100                 li->lcs = lc;
101                 ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
102         }
103         return( lc );
104 }
105
106 void
107 ldap_back_dobind(struct ldapconn *lc, Operation *op)
108 {
109         if (lc->bound)
110                 return;
111
112         if (ldap_bind_s(lc->ld, lc->conn->c_cdn, NULL, LDAP_AUTH_SIMPLE) !=
113                 LDAP_SUCCESS)
114                 ldap_back_op_result(lc, op);
115         else
116                 lc->bound = 1;
117 }
118
119 /* Map API errors to protocol errors... */
120
121 int
122 ldap_back_map_result(int err)
123 {
124         switch(err)
125         {
126         case LDAP_SERVER_DOWN:
127                 return LDAP_UNAVAILABLE;
128         case LDAP_LOCAL_ERROR:
129                 return LDAP_OPERATIONS_ERROR;
130         case LDAP_ENCODING_ERROR:
131         case LDAP_DECODING_ERROR:
132                 return LDAP_PROTOCOL_ERROR;
133         case LDAP_TIMEOUT:
134                 return LDAP_UNAVAILABLE;
135         case LDAP_AUTH_UNKNOWN:
136                 return LDAP_AUTH_METHOD_NOT_SUPPORTED;
137         case LDAP_FILTER_ERROR:
138                 return LDAP_OPERATIONS_ERROR;
139         case LDAP_USER_CANCELLED:
140                 return LDAP_OPERATIONS_ERROR;
141         case LDAP_PARAM_ERROR:
142                 return LDAP_PROTOCOL_ERROR;
143         case LDAP_NO_MEMORY:
144                 return LDAP_OPERATIONS_ERROR;
145         case LDAP_CONNECT_ERROR:
146                 return LDAP_UNAVAILABLE;
147         case LDAP_NOT_SUPPORTED:
148                 return LDAP_UNWILLING_TO_PERFORM;
149         case LDAP_CONTROL_NOT_FOUND:
150                 return LDAP_PROTOCOL_ERROR;
151         case LDAP_NO_RESULTS_RETURNED:
152                 return LDAP_NO_SUCH_OBJECT;
153         case LDAP_MORE_RESULTS_TO_RETURN:
154                 return LDAP_OTHER;
155         case LDAP_CLIENT_LOOP:
156         case LDAP_REFERRAL_LIMIT_EXCEEDED:
157                 return LDAP_LOOP_DETECT;
158         default:
159                 if LDAP_API_ERROR(err)
160                         return LDAP_OTHER;
161                 else
162                         return err;
163         }
164 }
165
166 int
167 ldap_back_op_result(struct ldapconn *lc, Operation *op)
168 {
169         int err;
170         char *msg;
171         char *match;
172
173         ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &err);
174         ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &msg);
175         ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
176         err = ldap_back_map_result(err);
177         send_ldap_result( lc->conn, op, err, match, msg, NULL, NULL );
178         free(match);
179         free(msg);
180         return( (err==LDAP_SUCCESS) ? 0 : -1 );
181 }