s3:utils: let smbstatus report anonymous signing/encryption explicitly
[samba.git] / source3 / libads / ads_struct.c
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 ADS_STATUS ads_build_path(const char *realm,
28                           const char *sep,
29                           const char *field,
30                           int reverse,
31                           char **_path)
32 {
33         char *p, *r;
34         int numbits = 0;
35         char *ret;
36         int len;
37         char *saveptr;
38
39         *_path = NULL;
40
41         r = SMB_STRDUP(realm);
42         if (r == NULL) {
43                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
44         }
45
46         for (p=r; *p; p++) {
47                 if (strchr(sep, *p)) {
48                         numbits++;
49                 }
50         }
51
52         len = (numbits+1)*(strlen(field)+1) + strlen(r) + 1;
53
54         ret = (char *)SMB_MALLOC(len);
55         if (!ret) {
56                 free(r);
57                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
58         }
59
60         if (strlcpy(ret,field, len) >= len) {
61                 /* Truncate ! */
62                 free(r);
63                 free(ret);
64                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
65         }
66         p=strtok_r(r, sep, &saveptr);
67         if (p) {
68                 if (strlcat(ret, p, len) >= len) {
69                         free(r);
70                         free(ret);
71                         return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
72                 }
73
74                 while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) {
75                         int retval;
76                         char *s = NULL;
77                         if (reverse)
78                                 retval = asprintf(&s, "%s%s,%s", field, p, ret);
79                         else
80                                 retval = asprintf(&s, "%s,%s%s", ret, field, p);
81                         free(ret);
82                         if (retval == -1) {
83                                 free(r);
84                                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
85                         }
86                         ret = SMB_STRDUP(s);
87                         free(s);
88                 }
89         }
90
91         free(r);
92
93         *_path = ret;
94
95         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 ADS_STATUS ads_build_dn(const char *realm, TALLOC_CTX *mem_ctx, char **_dn)
103 {
104         ADS_STATUS status;
105         char *dn = NULL;
106
107         status = ads_build_path(realm, ".", "dc=", 0, &dn);
108         if (!ADS_ERR_OK(status)) {
109                 SAFE_FREE(dn);
110                 return status;
111         }
112
113         *_dn = talloc_strdup(mem_ctx, dn);
114         SAFE_FREE(dn);
115         if (*_dn == NULL) {
116                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
117         }
118
119         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 char *ads_build_domain(const char *dn)
126 {
127         char *dnsdomain = NULL;
128
129         /* result should always be shorter than the DN */
130
131         if ( (dnsdomain = SMB_STRDUP( dn )) == NULL ) {
132                 DEBUG(0,("ads_build_domain: malloc() failed!\n"));              
133                 return NULL;            
134         }       
135
136         if (!strlower_m( dnsdomain )) {
137                 SAFE_FREE(dnsdomain);
138                 return NULL;
139         }
140
141         all_string_sub( dnsdomain, "dc=", "", 0);
142         all_string_sub( dnsdomain, ",", ".", 0 );
143
144         return dnsdomain;       
145 }
146
147 static int ads_destructor(ADS_STRUCT *ads)
148 {
149 #ifdef HAVE_LDAP
150         ads_disconnect(ads);
151 #endif
152         return 0;
153 }
154
155 /*
156   initialise a ADS_STRUCT, ready for some ads_ ops
157 */
158 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         ADS_STRUCT *ads = NULL;
165         int wrap_flags;
166
167         ads = talloc_zero(mem_ctx, ADS_STRUCT);
168         if (ads == NULL) {
169                 return NULL;
170         }
171         talloc_set_destructor(ads, ads_destructor);
172
173 #ifdef HAVE_LDAP
174         ads_zero_ldap(ads);
175 #endif
176
177         ads->server.realm = talloc_strdup(ads, realm);
178         if (realm != NULL && ads->server.realm == NULL) {
179                 DBG_WARNING("Out of memory\n");
180                 TALLOC_FREE(ads);
181                 return NULL;
182         }
183
184         ads->server.workgroup = talloc_strdup(ads, workgroup);
185         if (workgroup != NULL && ads->server.workgroup == NULL) {
186                 DBG_WARNING("Out of memory\n");
187                 TALLOC_FREE(ads);
188                 return NULL;
189         }
190
191         ads->server.ldap_server = talloc_strdup(ads, ldap_server);
192         if (ldap_server != NULL && ads->server.ldap_server == NULL) {
193                 DBG_WARNING("Out of memory\n");
194                 TALLOC_FREE(ads);
195                 return NULL;
196         }
197
198         wrap_flags = lp_client_ldap_sasl_wrapping();
199
200         if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
201                 sasl_state = ADS_SASL_PLAIN;
202         } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
203                 sasl_state = ADS_SASL_PLAIN;
204         }
205
206         switch (sasl_state) {
207         case ADS_SASL_PLAIN:
208                 break;
209         case ADS_SASL_SIGN:
210                 wrap_flags |= ADS_AUTH_SASL_SIGN;
211                 break;
212         case ADS_SASL_SEAL:
213                 wrap_flags |= ADS_AUTH_SASL_SEAL;
214                 break;
215         }
216
217         ads->auth.flags = wrap_flags;
218
219         ads->auth.reconnect_state = talloc_zero(ads,
220                                                 struct ads_reconnect_state);
221         if (ads->auth.reconnect_state == NULL) {
222                 TALLOC_FREE(ads);
223                 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         ads->config.ldap_page_size     = lp_ldap_page_size();
229
230         return ads;
231 }
232
233 /****************************************************************
234 ****************************************************************/
235
236 bool ads_set_sasl_wrap_flags(ADS_STRUCT *ads, unsigned flags)
237 {
238         unsigned reset_flags;
239         unsigned other_flags;
240
241         if (!ads) {
242                 return false;
243         }
244
245         reset_flags = ADS_AUTH_SASL_SIGN |
246                       ADS_AUTH_SASL_SEAL |
247                       ADS_AUTH_SASL_LDAPS |
248                       ADS_AUTH_SASL_STARTTLS;
249
250         other_flags = ads->auth.flags & ~reset_flags;
251
252         ads->auth.flags = flags | other_flags;
253
254         return true;
255 }