cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

policy_server.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 #include <policy_server.h>
26 
27 #include <eval_context.h>
28 #include <addr_lib.h>
29 #include <communication.h>
30 
31 #include <assert.h>
32 #include <logging.h>
33 #include <string_lib.h>
34 #include <file_lib.h>
35 
36 //*******************************************************************
37 // POLICY SERVER VARIABLES:
38 //*******************************************************************
39 
40 static char *POLICY_SERVER = NULL; // full bootstrap argument
41 static char *POLICY_SERVER_HOST = NULL; // only host part, if present
42 static char POLICY_SERVER_PORT[CF_MAX_PORT_LEN]; // only port part
43 static char POLICY_SERVER_IP[CF_MAX_IP_LEN]; // resolved IP
44 
45 
46 //*******************************************************************
47 // POLICY SERVER SET FUNCTION:
48 //*******************************************************************
49 
50 static bool is_whitespace_empty(const char *str) {
51  if(NULL_OR_EMPTY(str))
52  {
53  return true;
54  }
55  while (str[0] != '\0')
56  {
57  if (!isspace(str[0]))
58  {
59  return false;
60  }
61  ++str;
62  }
63  return true;
64 }
65 
66 /**
67  * @brief Sets both internal C variables as well as policy sys variables.
68  *
69  * Called at bootstrap and after reading policy_server.dat.
70  * Changes sys.policy_hub and sys.policy_hub_port.
71  * NULL is a valid input for new_policy_server, everything will be freed and
72  * set to NULL.
73  *
74  * @param ctx EvalContext is used to set related variables
75  * @param new_policy_server can be 'host:port', same as policy_server.dat
76  */
77 void PolicyServerSet(const char *new_policy_server)
78 {
79  // Clean up static variables:
84 
85  POLICY_SERVER_IP[0] = '\0';
86  POLICY_SERVER_PORT[0] = '\0';
87 
88  if (is_whitespace_empty(new_policy_server))
89  {
90  return;
91  }
92  else
93  {// Set POLICY_SERVER to be bootstrap argument/policy_server.dat contents
94  POLICY_SERVER = xstrdup(new_policy_server);
95  }
96 
97  // Parse policy server in a separate buffer:
98  char *host_or_ip, *port;
99  char *buffer = xstrdup(new_policy_server);
100 
101  AddressType address_type = ParseHostPort(buffer, &host_or_ip, &port);
102 
103  if (address_type == ADDRESS_TYPE_OTHER)
104  {
105  POLICY_SERVER_HOST = xstrdup(host_or_ip);
106  }
107  else // ADDRESS_TYPE_IPV4 or ADDRESS_TYPE_IPV6
108  {
109  assert(strlen(host_or_ip) < CF_MAX_IP_LEN);
110  strcpy(POLICY_SERVER_IP, host_or_ip);
111  }
112 
113  if ( ! NULL_OR_EMPTY(port) )
114  {
115  if(strlen(port) < CF_MAX_PORT_LEN)
116  {
117  strcpy(POLICY_SERVER_PORT, port);
118  }
119  else
120  {
122  "Too long port number in PolicyServerSet: '%s'",
123  port);
124  }
125  }
126 
127  free(buffer);
128 }
129 
130 
131 //*******************************************************************
132 // POLICY SERVER GET FUNCTIONS:
133 //*******************************************************************
134 
135 static char *CheckEmptyReturn(char *s)
136 {
137  return (NULL_OR_EMPTY(s)) ? NULL : s;
138 }
139 
140 /**
141  * @brief Used to access the internal POLICY_SERVER variable.
142  * @return Read-only string, can be 'host:port', same as policy_server.dat
143  * NULL if not bootstrapped ( not set ).
144  */
145 const char *PolicyServerGet()
146 {
147  return POLICY_SERVER; // Don't use CheckedReturn, var should be NULL!
148 }
149 
150 /**
151  * @brief Gets the IP address of policy server, does lookup if necessary.
152  * @return Read-only string, can be IPv4 or IPv6.
153  * NULL if not bootstrapped or lookup failed.
154  */
155 const char *PolicyServerGetIP()
156 {
157  if (POLICY_SERVER_HOST == NULL)
158  {
160  }
161  assert(POLICY_SERVER_HOST[0] != '\0');
163  CF_MAX_IP_LEN);
164  if (ret != 0) // Lookup failed
165  {
166  return NULL;
167  }
169 }
170 
171 /**
172  * @brief Gets the host part of what was bootstrapped to (without port).
173  * @return Read-only string, hostname part of bootstrap argument.
174  * NULL if not bootstrapped or bootstrapped to IP.
175  */
176 const char *PolicyServerGetHost()
177 {
178  return POLICY_SERVER_HOST; // Don't use CheckedReturn, var should be NULL!
179 }
180 
181 /**
182  * @brief Gets the port part of the policy server.
183  * @return Read-only null terminated string of port number.
184  * NULL if port not specified, or not bootstrapped at all.
185  */
186 const char *PolicyServerGetPort()
187 {
189 }
190 
191 //*******************************************************************
192 // POLICY SERVER FILE FUNCTIONS:
193 //*******************************************************************
194 
195 static char *PolicyServerFilename(const char *workdir)
196 {
197  return StringFormat("%s%cpolicy_server.dat", workdir, FILE_SEPARATOR);
198 }
199 
200 /**
201  * @brief Reads the policy_server.dat file.
202  * @param[in] workdir the directory of policy_server.dat usually GetWorkDir()
203  * @return Trimmed contents of policy_server.dat file. Null terminated.
204  */
205 char *PolicyServerReadFile(const char *workdir)
206 {
207  char contents[CF_MAX_SERVER_LEN] = "";
208 
209  char *filename = PolicyServerFilename(workdir);
210  FILE *fp = safe_fopen(filename, "r");
211  if (fp == NULL)
212  {
213  Log( LOG_LEVEL_VERBOSE, "Could not open file '%s' (fopen: %s)",
214  filename, GetErrorStr() );
215  free(filename);
216  return NULL;
217  }
218 
219  if (fgets(contents, CF_MAX_SERVER_LEN, fp) == NULL)
220  {
221  Log( LOG_LEVEL_VERBOSE, "Could not read file '%s' (fgets: %s)",
222  filename, GetErrorStr() );
223  free(filename);
224  fclose(fp);
225  return NULL;
226  }
227 
228  free(filename);
229  fclose(fp);
230  char *start = TrimWhitespace(contents);
231  return xstrdup(start);
232 }
233 
234 
235 /**
236  * @brief Reads and parses the policy_server.dat file.
237  *
238  * @code{.c}
239  * //Typical usage:
240  * char *host, *port;
241  * bool file_read = PolicyServerParseFile(GetWorkDir(), &host, &port);
242  * printf( "host is %s", file_read ? host : "unavailable" );
243  * free(host); free(port);
244  * @endcode
245  *
246  * @param[in] workdir The directory of policy_server.dat usually GetWorkDir()
247  * @param[out] host pointer at this address will be hostname string (strdup)
248  * @param[out] port pointer at this address will be port string (strdup)
249  * @attention host* and port* must be freed.
250  * @return Boolean indicating success.
251  */
252 bool PolicyServerParseFile(const char *workdir, char **host, char **port)
253 {
254  char *contents = PolicyServerReadFile(workdir);
255  if (contents == NULL)
256  {
257  return false;
258  }
259  (*host) = NULL;
260  (*port) = NULL;
261 
262  ParseHostPort(contents, host, port);
263 
264  // The file did not contain a host
265  if (*host == NULL)
266  {
267  return false;
268  }
269 
270  (*host) = xstrdup(*host);
271  if (*port != NULL)
272  {
273  (*port) = xstrdup(*port);
274  }
275  free(contents);
276  return true;
277 }
278 
279 /**
280  * @brief Reads and parses the policy_server.dat file.
281  *
282  * @param[in] workdir The directory of policy_server.dat usually GetWorkDir()
283  * @param[out] ipaddr pointer at this address will be hostname string (strdup)
284  * @param[out] port pointer at this address will be port string (strdup)
285  * @attention ipaddr* and port* must be freed.
286  * @return Boolean indicating success.
287  * @see PolicyServerParseFile
288  */
289 bool PolicyServerLookUpFile(const char *workdir, char **ipaddr, char **port)
290 {
291  char *host;
292  bool file_read = PolicyServerParseFile(workdir, &host, port);
293  if (file_read == false)
294  {
295  return false;
296  }
297  char tmp_ipaddr[CF_MAX_IP_LEN];
298  if (Hostname2IPString(tmp_ipaddr, host, sizeof(tmp_ipaddr)) == -1)
299  {
301  "Unable to resolve policy server host: %s", host);
302  free(host);
303  free(*port);
304  (*port) = NULL;
305  return false;
306  }
307  (*ipaddr) = xstrdup(tmp_ipaddr);
308  free(host);
309  return true;
310 }
311 
312 /**
313  * @brief Write new_policy_server to the policy_server.dat file.
314  * @param[in] workdir The directory of policy_server.dat, usually GetWorkDir()
315  * @param[in] new_policy_server The host:port string defining the server
316  * @return True if successful
317  */
318 bool PolicyServerWriteFile(const char *workdir, const char *new_policy_server)
319 {
320  char *filename = PolicyServerFilename(workdir);
321 
322  FILE *file = safe_fopen(filename, "w");
323  if (file == NULL)
324  {
325  Log(LOG_LEVEL_ERR, "Unable to write policy server file '%s' (fopen: %s)", filename, GetErrorStr());
326  free(filename);
327  return false;
328  }
329 
330  fprintf(file, "%s\n", new_policy_server);
331  fclose(file);
332 
333  free(filename);
334  return true;
335 }
336 
337 /**
338  * @brief Remove the policy_server.dat file
339  * @param[in] workdir The directory of policy_server.dat, usually GetWorkDir()
340  * @return True if successful
341  */
342 bool PolicyServerRemoveFile(const char *workdir)
343 {
344  char *filename = PolicyServerFilename(workdir);
345 
346  if (unlink(filename) != 0)
347  {
348  Log(LOG_LEVEL_ERR, "Unable to remove file '%s'. (unlink: %s)", filename, GetErrorStr());
349  free(filename);
350  return false;
351  }
352 
353  free(filename);
354  return true;
355 }
AddressType ParseHostPort(char *s, char **hostname, char **port)
Definition: addr_lib.c:588
AddressType
Definition: addr_lib.h:36
@ ADDRESS_TYPE_OTHER
Definition: addr_lib.h:37
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
void free(void *)
#define CF_MAX_PORT_LEN
Definition: cfnet.h:40
#define CF_MAX_SERVER_LEN
Definition: cfnet.h:43
#define CF_MAX_IP_LEN
Definition: cfnet.h:39
int Hostname2IPString(char *dst, const char *hostname, size_t dst_size)
DNS lookup of hostname, store the address as string into dst of size dst_size.
FILE * safe_fopen(const char *const path, const char *const mode)
Definition: file_lib.c:812
#define FILE_SEPARATOR
Definition: file_lib.h:102
#define NULL
Definition: getopt1.c:56
const char * GetErrorStr(void)
Definition: logging.c:275
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_WARNING
Definition: logging.h:43
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
bool PolicyServerRemoveFile(const char *workdir)
Remove the policy_server.dat file.
static char * CheckEmptyReturn(char *s)
bool PolicyServerWriteFile(const char *workdir, const char *new_policy_server)
Write new_policy_server to the policy_server.dat file.
const char * PolicyServerGetHost()
Gets the host part of what was bootstrapped to (without port).
char * PolicyServerReadFile(const char *workdir)
Reads the policy_server.dat file.
static char POLICY_SERVER_PORT[6]
Definition: policy_server.c:42
static char * PolicyServerFilename(const char *workdir)
void PolicyServerSet(const char *new_policy_server)
Sets both internal C variables as well as policy sys variables.
Definition: policy_server.c:77
bool PolicyServerParseFile(const char *workdir, char **host, char **port)
Reads and parses the policy_server.dat file.
static char * POLICY_SERVER_HOST
Definition: policy_server.c:41
const char * PolicyServerGetPort()
Gets the port part of the policy server.
static char POLICY_SERVER_IP[64]
Definition: policy_server.c:43
const char * PolicyServerGet()
Used to access the internal POLICY_SERVER variable.
static bool is_whitespace_empty(const char *str)
Definition: policy_server.c:50
static char * POLICY_SERVER
Definition: policy_server.c:40
const char * PolicyServerGetIP()
Gets the IP address of policy server, does lookup if necessary.
bool PolicyServerLookUpFile(const char *workdir, char **ipaddr, char **port)
Reads and parses the policy_server.dat file.
Access to Policy Server IP Address, hostname and port number.
char * TrimWhitespace(char *s)
Definition: string_lib.c:1196
char * StringFormat(const char *fmt,...)
Format string like sprintf and return formatted string allocated on heap as a return value.
Definition: string_lib.c:51
#define NULL_OR_EMPTY(str)
Definition: string_lib.h:43