summaryrefslogtreecommitdiffstats
path: root/worker/ipaaction.c
blob: de01d94a0507a7a7c787f5647bf3f2cfa586254c (plain)
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>


#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/relaxng.h>

#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>

#include <curl/curl.h>

#include "util.h"
#include "helpers.h"
#include "xml_helper.h"

#define XPATH_IPAACTION_CONDITION_COMMAND (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:command"
#define XPATH_IPAACTION_CONDITION_USER (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:user"
#define XPATH_IPAACTION_CONDITION_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:condition/def:group"

#define XPATH_IPAACTION_FILE_URL (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:url"
#define XPATH_IPAACTION_FILE_DATA (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:data"
#define XPATH_IPAACTION_FILE_PATH (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:path"
#define XPATH_IPAACTION_FILE_OWNER (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:owner"
#define XPATH_IPAACTION_FILE_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:group"
#define XPATH_IPAACTION_FILE_ACCESS (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:access"
#define XPATH_IPAACTION_FILE_SELINUX_CONTEXT (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:selinux_context"
#define XPATH_IPAACTION_FILE_CLEANUP (xmlChar *) "//def:ipa/def:ipaaction/def:file/def:cleanup"

#define XPATH_IPAACTION_RUN_COMMAND (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:command"
#define XPATH_IPAACTION_RUN_USER (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:user"
#define XPATH_IPAACTION_RUN_GROUP (xmlChar *) "//def:ipa/def:ipaaction/def:run/def:group"

char *find_value(const xmlDocPtr doc, const xmlChar *xpath_expr, const char *default_value) {
    char *val;
    val = find_by_xpath(doc, xpath_expr, FIND_VALUE);
    if (val==NULL) {
        DEBUG(3, ("No value found with XPath %s.\n", xpath_expr));
        if (default_value!=NULL) {
            DEBUG(3, ("Using default value %s.\n", default_value));
            val=strdup(default_value);
        }
    }

    return val;
}

int check_ipaaction_condition(const xmlDocPtr doc, const xmlChar *default_namespace) {
    int ret;
    char *condition;
    char *user;
    char *group;
    char *arguments;

    condition = find_value(doc, XPATH_IPAACTION_CONDITION_COMMAND, NULL);
    CHECK(condition, NULL, ("No condition found for current ipaaction.\n"), return 0);
    DEBUG(3, ("Found condition for current ipaaction: |%s|\n", condition));

    user = find_value(doc, XPATH_IPAACTION_CONDITION_USER, "nobody");
    DEBUG(3, ("Found user for condition: %s\n", user));

    group = find_value(doc, XPATH_IPAACTION_CONDITION_GROUP, "nobody");
    DEBUG(3, ("Found group for condition: %s\n", group));

    arguments=strchr(condition,' ');
    if (arguments!=NULL) {
        *arguments++='\0';
    }

    ret=exec_command(condition, user, group, arguments, NULL);

    free(arguments);
    free(group);
    free(user);
    free(condition);

    return ret;
}

int ipaaction_file(const xmlDocPtr doc, const xmlChar *default_namespace) {
    char *url;
    char *data;
    char *path;
    char *owner;
    char *group;
    char *access;
    char *selinux_context;
    //char **acl;
    char *cleanup;
    CURL *curl_context;
    CURLcode curl_result;
    char *tmp_file_name;
    FILE *output_file;
    int fd;
    int ret;
    struct stat stat_buffer;

    url = find_value(doc, XPATH_IPAACTION_FILE_URL, NULL);
    DEBUG(3, ("Found the following ipaaction file url: |%s|\n", url));
    data = find_value(doc, XPATH_IPAACTION_FILE_DATA, NULL);
    DEBUG(3, ("Found the following ipaaction file data: |%s|\n", data));
    if (url==NULL && data==NULL) {
        DEBUG(0,("Found no url or data element for ipaaction file. This should never happen.\n"));
        return -1;
    }
    if (url!=NULL && data!=NULL) {
        DEBUG(0,("Only url or data element are allowed for ipaaction file, not both. This should never happen.\n"));
        return -1;
    }

    path = find_value(doc, XPATH_IPAACTION_FILE_PATH, NULL);
    CHECK(path, NULL, ("Path for ipaaction file not found.\n"), return -1);
    DEBUG(3, ("Found path for ipaaction file: %s\n", path));
    ret=stat(path, &stat_buffer);
    CHECK(ret, 0, ("Destination file %s alread exists.\n", path), return -1); 

    owner = find_value(doc, XPATH_IPAACTION_FILE_OWNER, "root");
    DEBUG(3, ("Found owner for ipaaction file: %s\n", owner));

    group = find_value(doc, XPATH_IPAACTION_FILE_GROUP, "root");
    DEBUG(3, ("Found group for ipaaction file: %s\n", group));

    access = find_value(doc, XPATH_IPAACTION_FILE_ACCESS, "0400");
    DEBUG(3, ("Found access permissions for ipaaction file: %s\n", access));

    selinux_context = find_value(doc, XPATH_IPAACTION_FILE_SELINUX_CONTEXT, NULL);
    DEBUG(3, ("Found SELinux file context for ipaaction file: %s\n", selinux_context));

    cleanup = find_value(doc, XPATH_IPAACTION_FILE_CLEANUP, "no");
    DEBUG(3, ("Found cleanup information for ipaaction file: %s\n", cleanup));


    tmp_file_name=(char *) malloc(strlen(path)+7);
    CHECK(tmp_file_name,NULL, ("malloc failed."), return -1);
    strcpy(tmp_file_name, path);
    strcat(tmp_file_name, ".XXXXXX");
    fd=open_temporary_file(tmp_file_name, access, owner, group, selinux_context);
    CHECK(fd, -1, ("Failed to open temporary file.\n"), return -1);
    output_file=fdopen(fd,"w");
    CHECK(output_file, NULL, ("fdopen failed: %s\n", strerror(errno)), return -1);
    if (url!=NULL) {
        curl_context=curl_easy_init();
        CHECK(curl_context, NULL, ("curl_easy_init failed.\n"), return -1);
        curl_result=curl_easy_setopt(curl_context, CURLOPT_URL, url);
        DEBUG(3,("curl result: %d\n",curl_result));
        curl_result=curl_easy_setopt(curl_context, CURLOPT_WRITEDATA, output_file);
        DEBUG(3,("curl result: %d\n",curl_result));
    
        curl_result=curl_easy_perform(curl_context);
        DEBUG(3,("curl result: %d\n",curl_result));

        curl_easy_cleanup(curl_context);
    }

    fclose(output_file); /* this should close fd, too */
    ret=rename(tmp_file_name, path);
    CHECK_MINUS_ONE_RETURN(ret, ("Cannot rename %s to %s: %s\n", tmp_file_name, path, strerror(errno) ));
    free(tmp_file_name);

    return 0;
}

int ipaaction_run(const xmlDocPtr doc, const xmlChar *default_namespace) {
    int ret;
    char *command;
    char *user;
    char *group;
    char *arguments;

    command = find_value(doc, XPATH_IPAACTION_RUN_COMMAND, NULL);
    CHECK(command, NULL,
        ("No command in ipaaction run section found, this should neven happen.\n"),
        return -1);
    DEBUG(3, ("Found command for current ipaaction: |%s|\n", command));

    user = find_value(doc, XPATH_IPAACTION_RUN_USER, "nobody");
    DEBUG(3, ("Found user for ipaaction run command: %s\n", user));

    group = find_value(doc, XPATH_IPAACTION_RUN_GROUP, "nobody");
    DEBUG(3, ("Found group for ipaaction run command: %s\n", group));

    arguments=strchr(command,' ');
    if (arguments!=NULL) {
        *arguments++='\0';
    }

    ret=exec_command(command, user, group, arguments, NULL);

    free(arguments);
    free(group);
    free(user);
    free(command);

    return ret;

    return 0;
}

int handle_ipaaction(const char *policy_name, const xmlChar *default_namespace) {
    int ret;
    xmlDocPtr doc;

    doc = xmlParseFile(policy_name);
    CHECK(doc, NULL, ("Cannot parse document %s!\n", policy_name), exit(1));

    ret=check_ipaaction_condition(doc, default_namespace);   
    if (ret!=0) {
        DEBUG(0,("IPA action condition failed\n"));
        return -1;
    }

    ret=ipaaction_file(doc, default_namespace);   
    if (ret!=0) {
        DEBUG(0,("IPA action file failed\n"));
        return -1;
    }

    ret=ipaaction_run(doc, default_namespace);   
    if (ret!=0) {
        DEBUG(0,("IPA action run failed\n"));
        return -1;
    }

    xmlFreeDoc(doc);

    return 0; 
}