-
Notifications
You must be signed in to change notification settings - Fork 154
/
pull.c
166 lines (133 loc) · 5.18 KB
/
pull.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include <jansson.h>
#include "pull.h"
#include "http.h"
#include "json.h"
#include "log.h"
static void load_files(struct PullResponses *pull_responses_ptr, json_t *files_j) {
int i;
for (i = 0; i < json_array_size(files_j); i++) {
json_t *filename_j = json_array_get(files_j, i);
if (!json_is_string(filename_j)) {
return json_error_ret_void(files_j,
"Value of %dth element in 'files' does not have type string");
}
// Extend the files array.
pull_responses_ptr->files = (struct File *)realloc(
pull_responses_ptr->files,
((pull_responses_ptr->file_count)+1) * sizeof(struct File));
if (pull_responses_ptr->files == NULL) {
pam_log(LOG_PRIORITY_ERROR,
"Unable to allocate memory to store pull responses.");
}
pull_responses_ptr->files[pull_responses_ptr->file_count].name = strdup(
json_string_value(filename_j));
if (pull_responses_ptr->files[pull_responses_ptr->file_count].name == NULL) {
pam_log(LOG_PRIORITY_ERROR,
"Unable to allocate memory to store pull responses.");
}
json_error_t error;
json_t *file_contents_j = json_load_file(json_string_value(filename_j), 0, &error);
if (file_contents_j == NULL) {
pam_log(LOG_PRIORITY_ERROR, "Error loading JSON file: %s", error.text);
}
char *file_json = json_dumps(file_contents_j, JSON_INDENT(2));
pam_log(LOG_PRIORITY_DEBUG, "Loaded JSON from file %s:\n%s",
json_string_value(filename_j), file_json);
free(file_json);
pull_responses_ptr->files[pull_responses_ptr->file_count].contents = file_contents_j;
pull_responses_ptr->file_count++;
}
}
static void load_env_vars(struct PullResponses *pull_responses_ptr, json_t *env_vars_j) {
int i;
for (i = 0; i < json_array_size(env_vars_j); i++) {
json_t *env_var_name_j = json_array_get(env_vars_j, i);
if (!json_is_string(env_var_name_j)) {
return json_error_ret_void(env_vars_j,
"Value of %dth element in 'env_vars' does not have type string");
}
// Extend the env_vars array.
pull_responses_ptr->env_vars = (struct EnvVar *)realloc(
pull_responses_ptr->env_vars,
((pull_responses_ptr->env_var_count)+1) * sizeof(struct EnvVar));
if (pull_responses_ptr->env_vars == NULL) {
pam_log(LOG_PRIORITY_ERROR,
"Unable to allocate memory to store pull responses.");
}
pull_responses_ptr->env_vars[pull_responses_ptr->env_var_count].name = strdup(
json_string_value(env_var_name_j));
if (pull_responses_ptr->env_vars[pull_responses_ptr->env_var_count].name == NULL) {
pam_log(LOG_PRIORITY_ERROR,
"Unable to allocate memory to store pull responses.");
}
char *env_var_value = getenv(json_string_value(env_var_name_j));
pam_log(LOG_PRIORITY_DEBUG, "Loaded environment variable %s: %s",
json_string_value(env_var_name_j), env_var_value);
if (env_var_value != NULL) {
pull_responses_ptr->env_vars[pull_responses_ptr->env_var_count].value = strdup(
env_var_value);
} else {
// Make this safe to assign and free.
pull_responses_ptr->env_vars[pull_responses_ptr->env_var_count].value = strdup("");
}
pull_responses_ptr->env_var_count++;
}
}
void engine_pull(const char *endpoint, struct PullResponses *pull_responses_ptr) {
// Initialize empty responses, then fill it up as the user responses come in.
pull_responses_ptr->file_count = 0;
pull_responses_ptr->env_var_count = 0;
// An empty malloc here allows calling free() later without having to check anything.
pull_responses_ptr->files = (struct File *)malloc(0);
pull_responses_ptr->env_vars = (struct EnvVar *)malloc(0);
if (strcmp(endpoint, "") == 0) {
pam_log(LOG_PRIORITY_INFO, "Pull endpoint is empty; not proceeding.");
return;
}
// Get specification of what to pull from OPA.
json_t *result_j;
http_request(HTTP_METHOD_GET, endpoint, NULL, &result_j);
if (result_j == NULL) {
// Errors occurred during HTTP action will have ben logged there.
// Nothing to do.
return;
}
json_t *files_j = json_object_get(result_j, "files");
if (!json_is_array(files_j)) {
return json_error_ret_void(result_j,
"Value of field 'files' does not have type array in JSON response");
}
// Load requested JSON files.
load_files(pull_responses_ptr, files_j);
json_t *env_vars_j = json_object_get(result_j, "env_vars");
if (!json_is_array(env_vars_j)) {
return json_error_ret_void(result_j,
"Value of field 'env_vars' does not have type object in JSON response");
}
// Load requested environment variables.
load_env_vars(pull_responses_ptr, env_vars_j);
json_decref(result_j); // Clean up.
}
static void free_files(struct PullResponses *pull_responses_ptr) {
int i;
for (i = 0; i < pull_responses_ptr->file_count; i++) {
free(pull_responses_ptr->files[i].name);
json_decref(pull_responses_ptr->files[i].contents);
}
free(pull_responses_ptr->files);
}
static void free_env_vars(struct PullResponses *pull_responses_ptr) {
int i;
for (i = 0; i < pull_responses_ptr->env_var_count; i++) {
free(pull_responses_ptr->env_vars[i].name);
free(pull_responses_ptr->env_vars[i].value);
}
free(pull_responses_ptr->env_vars);
}
void free_pull_responses(struct PullResponses *pull_responses_ptr) {
free_files(pull_responses_ptr);
free_env_vars(pull_responses_ptr);
}