Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : ads (active directory) utility library
4 : Copyright (C) Andrew Tridgell 2001
5 : Copyright (C) Andrew Bartlett 2001
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include "includes.h"
22 : #include "ads.h"
23 :
24 : /* return a ldap dn path from a string, given separators and field name
25 : caller must free
26 : */
27 597 : ADS_STATUS ads_build_path(const char *realm,
28 : const char *sep,
29 : const char *field,
30 : int reverse,
31 : char **_path)
32 : {
33 0 : char *p, *r;
34 597 : int numbits = 0;
35 0 : char *ret;
36 0 : int len;
37 0 : char *saveptr;
38 :
39 597 : *_path = NULL;
40 :
41 597 : r = SMB_STRDUP(realm);
42 597 : if (r == NULL) {
43 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
44 : }
45 :
46 14252 : for (p=r; *p; p++) {
47 13655 : if (strchr(sep, *p)) {
48 1737 : numbits++;
49 : }
50 : }
51 :
52 597 : len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
53 :
54 597 : ret = (char *)SMB_MALLOC(len);
55 597 : if (!ret) {
56 0 : free(r);
57 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
58 : }
59 :
60 597 : if (strlcpy(ret,field, len) >= len) {
61 : /* Truncate ! */
62 0 : free(r);
63 0 : free(ret);
64 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
65 : }
66 597 : p=strtok_r(r, sep, &saveptr);
67 597 : if (p) {
68 597 : if (strlcat(ret, p, len) >= len) {
69 0 : free(r);
70 0 : free(ret);
71 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
72 : }
73 :
74 2334 : while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) {
75 0 : int retval;
76 1737 : char *s = NULL;
77 1737 : if (reverse)
78 0 : retval = asprintf(&s, "%s%s,%s", field, p, ret);
79 : else
80 1737 : retval = asprintf(&s, "%s,%s%s", ret, field, p);
81 1737 : free(ret);
82 1737 : if (retval == -1) {
83 0 : free(r);
84 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
85 : }
86 1737 : ret = SMB_STRDUP(s);
87 1737 : free(s);
88 : }
89 : }
90 :
91 597 : free(r);
92 :
93 597 : *_path = ret;
94 :
95 597 : return ADS_ERROR_NT(NT_STATUS_OK);
96 : }
97 :
98 : /* return a dn of the form "dc=AA,dc=BB,dc=CC" from a
99 : realm of the form AA.BB.CC
100 : caller must free
101 : */
102 595 : ADS_STATUS ads_build_dn(const char *realm, TALLOC_CTX *mem_ctx, char **_dn)
103 : {
104 0 : ADS_STATUS status;
105 595 : char *dn = NULL;
106 :
107 595 : status = ads_build_path(realm, ".", "dc=", 0, &dn);
108 595 : if (!ADS_ERR_OK(status)) {
109 0 : SAFE_FREE(dn);
110 0 : return status;
111 : }
112 :
113 595 : *_dn = talloc_strdup(mem_ctx, dn);
114 595 : SAFE_FREE(dn);
115 595 : if (*_dn == NULL) {
116 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
117 : }
118 :
119 595 : return ADS_ERROR_NT(NT_STATUS_OK);
120 : }
121 :
122 : /* return a DNS name in the for aa.bb.cc from the DN
123 : "dc=AA,dc=BB,dc=CC". caller must free
124 : */
125 20 : char *ads_build_domain(const char *dn)
126 : {
127 20 : char *dnsdomain = NULL;
128 :
129 : /* result should always be shorter than the DN */
130 :
131 20 : if ( (dnsdomain = SMB_STRDUP( dn )) == NULL ) {
132 0 : DEBUG(0,("ads_build_domain: malloc() failed!\n"));
133 0 : return NULL;
134 : }
135 :
136 20 : if (!strlower_m( dnsdomain )) {
137 0 : SAFE_FREE(dnsdomain);
138 0 : return NULL;
139 : }
140 :
141 20 : all_string_sub( dnsdomain, "dc=", "", 0);
142 20 : all_string_sub( dnsdomain, ",", ".", 0 );
143 :
144 20 : return dnsdomain;
145 : }
146 :
147 630 : static int ads_destructor(ADS_STRUCT *ads)
148 : {
149 : #ifdef HAVE_LDAP
150 630 : ads_disconnect(ads);
151 : #endif
152 630 : return 0;
153 : }
154 :
155 : /*
156 : initialise a ADS_STRUCT, ready for some ads_ ops
157 : */
158 630 : ADS_STRUCT *ads_init(TALLOC_CTX *mem_ctx,
159 : const char *realm,
160 : const char *workgroup,
161 : const char *ldap_server,
162 : enum ads_sasl_state_e sasl_state)
163 : {
164 630 : ADS_STRUCT *ads = NULL;
165 0 : int wrap_flags;
166 :
167 630 : ads = talloc_zero(mem_ctx, ADS_STRUCT);
168 630 : if (ads == NULL) {
169 0 : return NULL;
170 : }
171 630 : talloc_set_destructor(ads, ads_destructor);
172 :
173 : #ifdef HAVE_LDAP
174 630 : ads_zero_ldap(ads);
175 : #endif
176 :
177 630 : ads->server.realm = talloc_strdup(ads, realm);
178 630 : if (realm != NULL && ads->server.realm == NULL) {
179 0 : DBG_WARNING("Out of memory\n");
180 0 : TALLOC_FREE(ads);
181 0 : return NULL;
182 : }
183 :
184 630 : ads->server.workgroup = talloc_strdup(ads, workgroup);
185 630 : if (workgroup != NULL && ads->server.workgroup == NULL) {
186 0 : DBG_WARNING("Out of memory\n");
187 0 : TALLOC_FREE(ads);
188 0 : return NULL;
189 : }
190 :
191 630 : ads->server.ldap_server = talloc_strdup(ads, ldap_server);
192 630 : if (ldap_server != NULL && ads->server.ldap_server == NULL) {
193 0 : DBG_WARNING("Out of memory\n");
194 0 : TALLOC_FREE(ads);
195 0 : return NULL;
196 : }
197 :
198 630 : wrap_flags = lp_client_ldap_sasl_wrapping();
199 :
200 630 : if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
201 12 : sasl_state = ADS_SASL_PLAIN;
202 618 : } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
203 12 : sasl_state = ADS_SASL_PLAIN;
204 : }
205 :
206 630 : switch (sasl_state) {
207 290 : case ADS_SASL_PLAIN:
208 290 : break;
209 0 : case ADS_SASL_SIGN:
210 0 : wrap_flags |= ADS_AUTH_SASL_SIGN;
211 0 : break;
212 340 : case ADS_SASL_SEAL:
213 340 : wrap_flags |= ADS_AUTH_SASL_SEAL;
214 340 : break;
215 : }
216 :
217 630 : ads->auth.flags = wrap_flags;
218 :
219 630 : ads->auth.reconnect_state = talloc_zero(ads,
220 : struct ads_reconnect_state);
221 630 : if (ads->auth.reconnect_state == NULL) {
222 0 : TALLOC_FREE(ads);
223 0 : return NULL;
224 : }
225 :
226 : /* Start with the configured page size when the connection is new,
227 : * we will drop it by half we get a timeout. */
228 630 : ads->config.ldap_page_size = lp_ldap_page_size();
229 :
230 630 : return ads;
231 : }
232 :
233 : /****************************************************************
234 : ****************************************************************/
235 :
236 2 : bool ads_set_sasl_wrap_flags(ADS_STRUCT *ads, unsigned flags)
237 : {
238 0 : unsigned reset_flags;
239 0 : unsigned other_flags;
240 :
241 2 : if (!ads) {
242 0 : return false;
243 : }
244 :
245 2 : reset_flags = ADS_AUTH_SASL_SIGN |
246 : ADS_AUTH_SASL_SEAL |
247 : ADS_AUTH_SASL_LDAPS |
248 : ADS_AUTH_SASL_STARTTLS;
249 :
250 2 : other_flags = ads->auth.flags & ~reset_flags;
251 :
252 2 : ads->auth.flags = flags | other_flags;
253 :
254 2 : return true;
255 : }
|