1 /*
2    Unix SMB/CIFS implementation.
3    Low-level connections.tdb access functions
4    Copyright (C) Volker Lendecke 2007
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "smbd/globals.h"
23 #include "dbwrap/dbwrap.h"
24 #include "dbwrap/dbwrap_open.h"
25 #include "dbwrap/dbwrap_rbt.h"
26 #include "messages.h"
27 #include "conn_tdb.h"
28 #include "util_tdb.h"
29 
30 struct connections_forall_state {
31 	struct db_context *session_by_pid;
32 	int (*fn)(const struct connections_key *key,
33 		  const struct connections_data *data,
34 		  void *private_data);
35 	void *private_data;
36 	int count;
37 };
38 
39 struct connections_forall_session {
40 	uid_t uid;
41 	gid_t gid;
42 	fstring machine;
43 	fstring addr;
44 	uint16_t cipher;
45 	uint16_t dialect;
46 	uint8_t signing_flags;
47 };
48 
collect_sessions_fn(struct smbXsrv_session_global0 * global,void * connections_forall_state)49 static int collect_sessions_fn(struct smbXsrv_session_global0 *global,
50 			       void *connections_forall_state)
51 {
52 	NTSTATUS status;
53 	struct connections_forall_state *state =
54 		(struct connections_forall_state*)connections_forall_state;
55 
56 	uint32_t id = global->session_global_id;
57 	struct connections_forall_session sess;
58 
59 	if (global->auth_session_info == NULL) {
60 		sess.uid = -1;
61 		sess.gid = -1;
62 	} else {
63 		sess.uid = global->auth_session_info->unix_token->uid;
64 		sess.gid = global->auth_session_info->unix_token->gid;
65 	}
66 	fstrcpy(sess.machine, global->channels[0].remote_name);
67 	fstrcpy(sess.addr, global->channels[0].remote_address);
68 	sess.cipher = global->channels[0].encryption_cipher;
69 	sess.dialect = global->connection_dialect;
70 	sess.signing_flags = global->signing_flags;
71 
72 	status = dbwrap_store(state->session_by_pid,
73 			      make_tdb_data((void*)&id, sizeof(id)),
74 			      make_tdb_data((void*)&sess, sizeof(sess)),
75 			      TDB_INSERT);
76 	if (!NT_STATUS_IS_OK(status)) {
77 		DEBUG(0, ("Failed to store record: %s\n", nt_errstr(status)));
78 	}
79 	return 0;
80 }
81 
traverse_tcon_fn(struct smbXsrv_tcon_global0 * global,void * connections_forall_state)82 static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
83 			    void *connections_forall_state)
84 {
85 	NTSTATUS status;
86 	struct connections_forall_state *state =
87 		(struct connections_forall_state*)connections_forall_state;
88 
89 	struct connections_key key;
90 	struct connections_data data;
91 
92 	uint32_t sess_id = global->session_global_id;
93 	struct connections_forall_session sess = {
94 		.uid = -1,
95 		.gid = -1,
96 	};
97 
98 	TDB_DATA val = tdb_null;
99 
100 	/*
101 	 * Note: that share_name is defined as array without a pointer.
102 	 * that's why it's always a valid pointer here.
103 	 */
104 	if (strlen(global->share_name) == 0) {
105 		/*
106 		 * when a smbXsrv_tcon is created it's created
107 		 * with empty share_name first in order to allocate
108 		 * an id, before filling in the details.
109 		 */
110 		return 0;
111 	}
112 
113 	status = dbwrap_fetch(state->session_by_pid, state,
114 			      make_tdb_data((void*)&sess_id, sizeof(sess_id)),
115 			      &val);
116 	if (NT_STATUS_IS_OK(status)) {
117 		memcpy((uint8_t *)&sess, val.dptr, val.dsize);
118 	}
119 
120 	ZERO_STRUCT(key);
121 	ZERO_STRUCT(data);
122 
123 	key.pid = data.pid = global->server_id;
124 	key.cnum = data.cnum = global->tcon_global_id;
125 	fstrcpy(key.name, global->share_name);
126 	fstrcpy(data.servicename, global->share_name);
127 	data.uid = sess.uid;
128 	data.gid = sess.gid;
129 	fstrcpy(data.addr, sess.addr);
130 	fstrcpy(data.machine, sess.machine);
131 	data.start = nt_time_to_unix(global->creation_time);
132 	data.encryption_flags = global->encryption_flags;
133 	data.cipher = sess.cipher;
134 	data.dialect = sess.dialect;
135 	data.signing_flags = global->signing_flags;
136 
137 	state->count++;
138 
139 	return state->fn(&key, &data, state->private_data);
140 }
141 
connections_forall_read(int (* fn)(const struct connections_key * key,const struct connections_data * data,void * private_data),void * private_data)142 int connections_forall_read(int (*fn)(const struct connections_key *key,
143 				      const struct connections_data *data,
144 				      void *private_data),
145 			    void *private_data)
146 {
147 	TALLOC_CTX *frame = talloc_stackframe();
148 	struct connections_forall_state *state =
149 		talloc_zero(talloc_tos(), struct connections_forall_state);
150 	NTSTATUS status;
151 	int ret = -1;
152 
153 	state->session_by_pid = db_open_rbt(state);
154 	state->fn = fn;
155 	state->private_data = private_data;
156 	status = smbXsrv_session_global_traverse(collect_sessions_fn, state);
157 	if (!NT_STATUS_IS_OK(status)) {
158 		DEBUG(0, ("Failed to traverse sessions: %s\n",
159 			  nt_errstr(status)));
160 		goto done;
161 	}
162 
163 	status = smbXsrv_tcon_global_traverse(traverse_tcon_fn, state);
164 	if (!NT_STATUS_IS_OK(status)) {
165 		DEBUG(0, ("Failed to traverse tree connects: %s\n",
166 			  nt_errstr(status)));
167 		goto done;
168 	}
169 	ret = state->count;
170 done:
171 	talloc_free(frame);
172 	return ret;
173 }
174