1 | /*
|
---|
2 | Unix SMB/CIFS implementation.
|
---|
3 | KCC service periodic handling
|
---|
4 |
|
---|
5 | Copyright (C) CrÃstian Deives
|
---|
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 |
|
---|
22 | #include "includes.h"
|
---|
23 | #include "lib/events/events.h"
|
---|
24 | #include "dsdb/samdb/samdb.h"
|
---|
25 | #include "auth/auth.h"
|
---|
26 | #include "smbd/service.h"
|
---|
27 | #include "lib/messaging/irpc.h"
|
---|
28 | #include "dsdb/kcc/kcc_service.h"
|
---|
29 | #include "dsdb/kcc/kcc_connection.h"
|
---|
30 | #include <ldb_errors.h>
|
---|
31 | #include "../lib/util/dlinklist.h"
|
---|
32 | #include "librpc/gen_ndr/ndr_misc.h"
|
---|
33 | #include "librpc/gen_ndr/ndr_drsuapi.h"
|
---|
34 | #include "librpc/gen_ndr/ndr_drsblobs.h"
|
---|
35 | #include "param/param.h"
|
---|
36 |
|
---|
37 | static int kccsrv_add_connection(struct kccsrv_service *s,
|
---|
38 | struct kcc_connection *conn)
|
---|
39 | {
|
---|
40 | struct ldb_message *msg;
|
---|
41 | TALLOC_CTX *tmp_ctx;
|
---|
42 | struct ldb_dn *new_dn, *server_dn;
|
---|
43 | struct GUID guid;
|
---|
44 | /* struct ldb_val schedule_val; */
|
---|
45 | int ret;
|
---|
46 | bool ok;
|
---|
47 |
|
---|
48 | tmp_ctx = talloc_new(s);
|
---|
49 | new_dn = samdb_ntds_settings_dn(s->samdb);
|
---|
50 | if (!new_dn) {
|
---|
51 | DEBUG(0, ("failed to find NTDS settings\n"));
|
---|
52 | ret = LDB_ERR_OPERATIONS_ERROR;
|
---|
53 | goto done;
|
---|
54 | }
|
---|
55 | new_dn = ldb_dn_copy(tmp_ctx, new_dn);
|
---|
56 | if (!new_dn) {
|
---|
57 | DEBUG(0, ("failed to copy NTDS settings\n"));
|
---|
58 | ret = LDB_ERR_OPERATIONS_ERROR;
|
---|
59 | goto done;
|
---|
60 | }
|
---|
61 | guid = GUID_random();
|
---|
62 | ok = ldb_dn_add_child_fmt(new_dn, "CN=%s", GUID_string(tmp_ctx, &guid));
|
---|
63 | if (!ok) {
|
---|
64 | DEBUG(0, ("failed to create nTDSConnection DN\n"));
|
---|
65 | ret = LDB_ERR_INVALID_DN_SYNTAX;
|
---|
66 | goto done;
|
---|
67 | }
|
---|
68 | ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &conn->dsa_guid, &server_dn);
|
---|
69 | if (ret != LDB_SUCCESS) {
|
---|
70 | DEBUG(0, ("failed to find fromServer DN '%s'\n",
|
---|
71 | GUID_string(tmp_ctx, &conn->dsa_guid)));
|
---|
72 | goto done;
|
---|
73 | }
|
---|
74 | /*schedule_val = data_blob_const(r1->schedule, sizeof(r1->schedule));*/
|
---|
75 |
|
---|
76 | msg = ldb_msg_new(tmp_ctx);
|
---|
77 | msg->dn = new_dn;
|
---|
78 | ldb_msg_add_string(msg, "objectClass", "nTDSConnection");
|
---|
79 | ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
|
---|
80 | ldb_msg_add_string(msg, "enabledConnection", "TRUE");
|
---|
81 | ldb_msg_add_linearized_dn(msg, "fromServer", server_dn);
|
---|
82 | /* ldb_msg_add_value(msg, "schedule", &schedule_val, NULL); */
|
---|
83 | samdb_msg_add_uint(s->samdb, msg, msg, "options", 1);
|
---|
84 |
|
---|
85 | ret = ldb_add(s->samdb, msg);
|
---|
86 | if (ret == LDB_SUCCESS) {
|
---|
87 | DEBUG(2, ("added nTDSConnection object '%s'\n",
|
---|
88 | ldb_dn_get_linearized(new_dn)));
|
---|
89 | } else {
|
---|
90 | DEBUG(0, ("failed to add an nTDSConnection object: %s\n",
|
---|
91 | ldb_strerror(ret)));
|
---|
92 | }
|
---|
93 |
|
---|
94 | done:
|
---|
95 | talloc_free(tmp_ctx);
|
---|
96 | return ret;
|
---|
97 | }
|
---|
98 |
|
---|
99 | static int kccsrv_delete_connection(struct kccsrv_service *s,
|
---|
100 | struct kcc_connection *conn)
|
---|
101 | {
|
---|
102 | TALLOC_CTX *tmp_ctx;
|
---|
103 | struct ldb_dn *dn;
|
---|
104 | int ret;
|
---|
105 |
|
---|
106 | tmp_ctx = talloc_new(s);
|
---|
107 | ret = dsdb_find_dn_by_guid(s->samdb, tmp_ctx, &conn->obj_guid, &dn);
|
---|
108 | if (ret != LDB_SUCCESS) {
|
---|
109 | DEBUG(0, ("failed to find nTDSConnection's DN: %s\n",
|
---|
110 | ldb_strerror(ret)));
|
---|
111 | goto done;
|
---|
112 | }
|
---|
113 |
|
---|
114 | ret = ldb_delete(s->samdb, dn);
|
---|
115 | if (ret == LDB_SUCCESS) {
|
---|
116 | DEBUG(2, ("deleted nTDSConnection object '%s'\n",
|
---|
117 | ldb_dn_get_linearized(dn)));
|
---|
118 | } else {
|
---|
119 | DEBUG(0, ("failed to delete an nTDSConnection object: %s\n",
|
---|
120 | ldb_strerror(ret)));
|
---|
121 | }
|
---|
122 |
|
---|
123 | done:
|
---|
124 | talloc_free(tmp_ctx);
|
---|
125 | return ret;
|
---|
126 | }
|
---|
127 |
|
---|
128 | void kccsrv_apply_connections(struct kccsrv_service *s,
|
---|
129 | struct kcc_connection_list *ntds_list,
|
---|
130 | struct kcc_connection_list *dsa_list)
|
---|
131 | {
|
---|
132 | unsigned int i, j, deleted = 0, added = 0;
|
---|
133 | int ret;
|
---|
134 |
|
---|
135 | for (i = 0; ntds_list && i < ntds_list->count; i++) {
|
---|
136 | struct kcc_connection *ntds = &ntds_list->servers[i];
|
---|
137 | for (j = 0; j < dsa_list->count; j++) {
|
---|
138 | struct kcc_connection *dsa = &dsa_list->servers[j];
|
---|
139 | if (GUID_equal(&ntds->dsa_guid, &dsa->dsa_guid)) {
|
---|
140 | break;
|
---|
141 | }
|
---|
142 | }
|
---|
143 | if (j == dsa_list->count) {
|
---|
144 | ret = kccsrv_delete_connection(s, ntds);
|
---|
145 | if (ret == LDB_SUCCESS) {
|
---|
146 | deleted++;
|
---|
147 | }
|
---|
148 | }
|
---|
149 | }
|
---|
150 | DEBUG(4, ("%d connections have been deleted\n", deleted));
|
---|
151 |
|
---|
152 | for (i = 0; i < dsa_list->count; i++) {
|
---|
153 | struct kcc_connection *dsa = &dsa_list->servers[i];
|
---|
154 | for (j = 0; ntds_list && j < ntds_list->count; j++) {
|
---|
155 | struct kcc_connection *ntds = &ntds_list->servers[j];
|
---|
156 | if (GUID_equal(&dsa->dsa_guid, &ntds->dsa_guid)) {
|
---|
157 | break;
|
---|
158 | }
|
---|
159 | }
|
---|
160 | if (ntds_list == NULL || j == ntds_list->count) {
|
---|
161 | ret = kccsrv_add_connection(s, dsa);
|
---|
162 | if (ret == LDB_SUCCESS) {
|
---|
163 | added++;
|
---|
164 | }
|
---|
165 | }
|
---|
166 | }
|
---|
167 | DEBUG(4, ("%d connections have been added\n", added));
|
---|
168 | }
|
---|
169 |
|
---|
170 | struct kcc_connection_list *kccsrv_find_connections(struct kccsrv_service *s,
|
---|
171 | TALLOC_CTX *mem_ctx)
|
---|
172 | {
|
---|
173 | unsigned int i;
|
---|
174 | int ret;
|
---|
175 | struct ldb_dn *base_dn;
|
---|
176 | struct ldb_result *res;
|
---|
177 | const char *attrs[] = { "objectGUID", "fromServer", NULL };
|
---|
178 | struct kcc_connection_list *list;
|
---|
179 |
|
---|
180 | kcctpl_test(s);
|
---|
181 |
|
---|
182 | base_dn = samdb_ntds_settings_dn(s->samdb);
|
---|
183 | if (!base_dn) {
|
---|
184 | DEBUG(0, ("failed to find our own NTDS settings DN\n"));
|
---|
185 | return NULL;
|
---|
186 | }
|
---|
187 |
|
---|
188 | ret = ldb_search(s->samdb, mem_ctx, &res, base_dn, LDB_SCOPE_ONELEVEL,
|
---|
189 | attrs, "objectClass=nTDSConnection");
|
---|
190 | if (ret != LDB_SUCCESS) {
|
---|
191 | DEBUG(0, ("failed nTDSConnection search: %s\n",
|
---|
192 | ldb_strerror(ret)));
|
---|
193 | return NULL;
|
---|
194 | }
|
---|
195 |
|
---|
196 | list = talloc(mem_ctx, struct kcc_connection_list);
|
---|
197 | if (!list) {
|
---|
198 | DEBUG(0, ("out of memory"));
|
---|
199 | return NULL;
|
---|
200 | }
|
---|
201 | list->servers = talloc_array(mem_ctx, struct kcc_connection,
|
---|
202 | res->count);
|
---|
203 | if (!list->servers) {
|
---|
204 | DEBUG(0, ("out of memory"));
|
---|
205 | return NULL;
|
---|
206 | }
|
---|
207 | list->count = 0;
|
---|
208 |
|
---|
209 | for (i = 0; i < res->count; i++) {
|
---|
210 | struct ldb_dn *server_dn;
|
---|
211 |
|
---|
212 | list->servers[i].obj_guid = samdb_result_guid(res->msgs[i],
|
---|
213 | "objectGUID");
|
---|
214 | server_dn = samdb_result_dn(s->samdb, mem_ctx, res->msgs[i],
|
---|
215 | "fromServer", NULL);
|
---|
216 | ret = dsdb_find_guid_by_dn(s->samdb, server_dn,
|
---|
217 | &list->servers[i].dsa_guid);
|
---|
218 | if (ret != LDB_SUCCESS) {
|
---|
219 | DEBUG(0, ("Failed to find connection server's GUID by "
|
---|
220 | "DN=%s: %s\n",
|
---|
221 | ldb_dn_get_linearized(server_dn),
|
---|
222 | ldb_strerror(ret)));
|
---|
223 | continue;
|
---|
224 | }
|
---|
225 | list->count++;
|
---|
226 | }
|
---|
227 | DEBUG(4, ("found %d existing nTDSConnection objects\n", list->count));
|
---|
228 | return list;
|
---|
229 | }
|
---|