summaryrefslogtreecommitdiff
path: root/src/lib/irm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/irm.c')
-rw-r--r--src/lib/irm.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/src/lib/irm.c b/src/lib/irm.c
index da3cfb62..ca2111ca 100644
--- a/src/lib/irm.c
+++ b/src/lib/irm.c
@@ -22,6 +22,7 @@
#define OUROBOROS_PREFIX "libouroboros-irm"
+#include <ouroboros/config.h>
#include <ouroboros/errno.h>
#include <ouroboros/irm.h>
#include <ouroboros/common.h>
@@ -29,6 +30,7 @@
#include <ouroboros/sockets.h>
#include <stdbool.h>
+#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
@@ -239,6 +241,84 @@ int irm_enroll_ipcp(pid_t api,
return ret;
}
+static int check_ap(char * ap_name)
+{
+ struct stat s;
+
+ if (stat(ap_name, &s) != 0)
+ return -ENOENT;
+
+ if (!(s.st_mode & S_IXUSR))
+ return -EPERM;
+
+ return 0;
+}
+
+static int check_ap_path(char ** ap_name)
+{
+ char * path = getenv("PATH");
+ char * path_end = path + strlen(path) + 1;
+ char * pstart;
+ char * pstop = path;
+ char * tmp;
+ char * tstop;
+ char * tstart;
+ bool perm = true;
+ int ret = 0;
+
+ if (*ap_name == NULL || path == NULL)
+ return -EINVAL;
+
+ if (!strlen(path) || strchr(*ap_name, '/') == NULL)
+ if ((ret = check_ap(*ap_name)) < 0)
+ return ret;
+
+ tmp = malloc(strlen(path) + strlen(*ap_name) + 2);
+ if (tmp == NULL)
+ return -ENOMEM;
+
+ tstop = tmp + strlen(path) + 1;
+ strcpy(tstop--, *ap_name);
+
+ while (pstop < path_end) {
+ ret = 0;
+ pstart = pstop;
+ if (*pstart != '/') {
+ free(tmp);
+ return -EINVAL;
+ }
+
+ while (*pstop != '\0' && *pstop != ':')
+ pstop++;
+
+ *pstop = '\0';
+ tstart = tstop - (pstop++ - pstart);
+ strcpy(tstart, pstart);
+ *tstop = '/';
+
+ if ((ret = check_ap(tstart)) < 0) {
+ if (ret == -EPERM)
+ perm = false;
+ continue;
+ }
+
+ free(*ap_name);
+ *ap_name = strdup(tstart);
+ free(tmp);
+
+ if (*ap_name == NULL)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ free(tmp);
+ if (!perm)
+ return -EPERM;
+
+ return -ENOENT;
+}
+
int irm_bind(char * name,
char * ap_name,
uint16_t opts,
@@ -248,20 +328,23 @@ int irm_bind(char * name,
irm_msg_t msg = IRM_MSG__INIT;
irm_msg_t * recv_msg = NULL;
int ret = -1;
- struct stat s;
+ char * full_ap_name;
if (name == NULL || ap_name == NULL)
return -EINVAL;
- if (stat(ap_name, &s) != 0)
- return -ENOENT;
+ full_ap_name = strdup(ap_name);
+ if (full_ap_name == NULL)
+ return -ENOMEM;
- if (!(s.st_mode & S_IXUSR))
- return -EPERM;
+ if ((ret = check_ap_path(&full_ap_name)) < 0) {
+ free(full_ap_name);
+ return ret;
+ }
msg.code = IRM_MSG_CODE__IRM_BIND;
msg.dst_name = name;
- msg.ap_name = ap_name;
+ msg.ap_name = full_ap_name;
if (argv != NULL) {
msg.n_args = argc;
@@ -283,6 +366,7 @@ int irm_bind(char * name,
ret = recv_msg->result;
irm_msg__free_unpacked(recv_msg, NULL);
+ free(full_ap_name);
return ret;
}