r18986: Add some more GPO download helper functions.
[tprouty/samba.git] / source / libgpo / gpo_fetch.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Group Policy Object Support
4  *  Copyright (C) Guenther Deschner 2005-2006
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 2 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, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 /****************************************************************
24  explode the GPO CIFS URI into their components
25 ****************************************************************/
26
27 NTSTATUS ads_gpo_explode_filesyspath(ADS_STRUCT *ads, 
28                                      TALLOC_CTX *mem_ctx, 
29                                      const char *file_sys_path, 
30                                      char **server, 
31                                      char **service, 
32                                      char **nt_path,
33                                      char **unix_path)
34 {
35         fstring tok;
36         pstring path;
37
38         *server = NULL;
39         *service = NULL;
40         *nt_path = NULL;
41         *unix_path = NULL;
42
43         if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
44                 return NT_STATUS_INVALID_PARAMETER;
45         }
46
47         if ((*server = talloc_strdup(mem_ctx, tok)) == NULL) {
48                 return NT_STATUS_NO_MEMORY;
49         }
50
51         if (!next_token(&file_sys_path, tok, "\\", sizeof(tok))) {
52                 return NT_STATUS_INVALID_PARAMETER;
53         }
54
55         if ((*service = talloc_strdup(mem_ctx, tok)) == NULL) {
56                 return NT_STATUS_NO_MEMORY;
57         }
58
59         if ((*nt_path = talloc_asprintf(mem_ctx, "\\%s", file_sys_path)) == NULL) {
60                 return NT_STATUS_NO_MEMORY;
61         }
62
63         pstrcpy(path, lock_path(GPO_CACHE_DIR));
64         pstrcat(path, "/");
65         pstrcat(path, file_sys_path);
66         pstring_sub(path, "\\", "/");
67
68         if ((*unix_path = talloc_strdup(mem_ctx, path)) == NULL) {
69                 return NT_STATUS_NO_MEMORY;
70         }
71
72         return NT_STATUS_OK;
73 }
74
75 /****************************************************************
76  prepare the local disc storage for "unix_path"
77 ****************************************************************/
78
79 NTSTATUS ads_gpo_prepare_local_store(ADS_STRUCT *ads, 
80                                      TALLOC_CTX *mem_ctx, 
81                                      const char *unix_path)
82 {
83         const char *top_dir = lock_path(GPO_CACHE_DIR);
84         char *current_dir;
85         fstring tok;
86
87         current_dir = talloc_strdup(mem_ctx, top_dir);
88         NT_STATUS_HAVE_NO_MEMORY(current_dir);
89
90         if ((mkdir(top_dir, 0644)) < 0 && errno != EEXIST) {
91                 return NT_STATUS_ACCESS_DENIED;
92         }
93
94         while (next_token(&unix_path, tok, "/", sizeof(tok))) {
95         
96                 if (strequal(tok, GPO_CACHE_DIR)) {
97                         break;
98                 }
99         }
100
101         while (next_token(&unix_path, tok, "/", sizeof(tok))) {
102
103                 current_dir = talloc_asprintf_append(current_dir, "/%s", tok);
104                 NT_STATUS_HAVE_NO_MEMORY(current_dir);
105
106                 if ((mkdir(current_dir, 0644)) < 0 && errno != EEXIST) {
107                         return NT_STATUS_ACCESS_DENIED;
108                 }
109         }
110
111         return NT_STATUS_OK;
112 }
113
114 /****************************************************************
115  download a full GPO via CIFS
116 ****************************************************************/
117
118 NTSTATUS ads_fetch_gpo_files(ADS_STRUCT *ads, 
119                             TALLOC_CTX *mem_ctx, 
120                             struct cli_state *cli, 
121                             struct GROUP_POLICY_OBJECT *gpo)
122 {
123         NTSTATUS result;
124         int fnum = 0;
125         int fd = 0;
126         char *data = NULL;
127         static int io_bufsize = 64512;
128         int read_size = io_bufsize;
129         char *server, *service, *nt_path, *unix_path, *nt_ini_path, *unix_ini_path;
130         off_t start = 0;
131         off_t nread = 0;
132
133         result = ads_gpo_explode_filesyspath(ads, mem_ctx, gpo->file_sys_path, 
134                                              &server, &service, &nt_path, &unix_path);
135         if (!NT_STATUS_IS_OK(result)) {
136                 goto out;
137         }
138
139         result = ads_gpo_prepare_local_store(ads, mem_ctx, unix_path);
140         if (!NT_STATUS_IS_OK(result)) {
141                 goto out;
142         }
143
144         unix_ini_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
145         nt_ini_path = talloc_asprintf(mem_ctx, "%s\\%s", nt_path, GPT_INI);
146         if (!unix_path || !nt_ini_path) {
147                 result = NT_STATUS_NO_MEMORY;
148                 goto out;
149         }
150
151         /* open local file */
152
153         fd = sys_open(unix_ini_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
154         if (fd == -1) {
155                 result = map_nt_error_from_unix(errno);
156                 goto out;
157         }
158          
159         /* open remote file */
160
161         fnum = cli_open(cli, nt_ini_path, O_RDONLY, DENY_NONE);
162         if (fnum == -1) {
163                 result = NT_STATUS_NO_SUCH_FILE;
164                 goto out;
165         }
166
167         /* copy gpt.ini */
168
169         data = (char *)SMB_MALLOC(read_size);
170         if (data == NULL) {
171                 result = NT_STATUS_NO_MEMORY;
172                 goto out;
173         }
174
175         while (1) {
176
177                 int n = cli_read(cli, fnum, data, nread + start, read_size);
178
179                 if (n <= 0)
180                         break;
181
182                 if (write(fd, data, n) != n) {
183                         break;
184                 }
185
186                 nread += n;
187         }
188
189         result = NT_STATUS_OK;
190
191  out:
192         SAFE_FREE(data);
193         if (fd) {
194                 close(fd);
195         }
196         if (fnum) {
197                 cli_close(cli, fnum);
198         }
199
200         return result;
201 }
202
203 /****************************************************************
204  get the locally stored gpt.ini version number
205 ****************************************************************/
206
207 NTSTATUS ads_gpo_get_sysvol_gpt_version(ADS_STRUCT *ads, 
208                                         TALLOC_CTX *mem_ctx, 
209                                         const char *unix_path, 
210                                         uint32 *sysvol_version,
211                                         char **display_name)
212 {
213         NTSTATUS status;
214         uint32 version;
215         char *local_path = NULL;
216         char *name = NULL;
217
218         local_path = talloc_asprintf(mem_ctx, "%s/%s", unix_path, GPT_INI);
219         NT_STATUS_HAVE_NO_MEMORY(local_path);
220
221         status = parse_gpt_ini(mem_ctx, local_path, &version, &name);
222         if (!NT_STATUS_IS_OK(status)) {
223                 DEBUG(10,("ads_gpo_get_sysvol_gpt_version: failed to parse ini [%s]: %s\n", 
224                         unix_path, nt_errstr(status)));
225                 return status;
226         }
227
228         if (sysvol_version) {
229                 *sysvol_version = version;
230         }
231
232         if (name && *display_name) {
233                 *display_name = talloc_strdup(mem_ctx, name);
234         }
235
236         return NT_STATUS_OK;
237 }