#include "para.h"
#include "net.h"
#include "string.h"
-#include <netdb.h>
#include "error.h"
-extern void (*crypt_function_recv)(unsigned long len, const unsigned char *indata, unsigned char *outdata);
-extern void (*crypt_function_send)(unsigned long len, const unsigned char *indata, unsigned char *outdata);
+static crypt_function **crypt_functions;
+static unsigned max_crypt_fd;
+void enable_crypt(int fd, crypt_function *recv, crypt_function *send)
+{
+ if (max_crypt_fd < fd) {
+ crypt_functions = para_realloc(crypt_functions,
+ 2 * (fd + 1) * sizeof(crypt_function*));
+ max_crypt_fd = fd;
+ }
+ crypt_functions[2 * fd] = recv;
+ crypt_functions[2 * fd + 1] = send;
+ PARA_INFO_LOG("rc4 encryption activated for fd %d\n", fd);
+}
+
+void disable_crypt(int fd)
+{
+ crypt_functions[2 * fd] = NULL;
+ crypt_functions[2 * fd + 1] = NULL;
+}
-#ifndef HAVE_UCRED
- struct ucred {
- uid_t uid, pid, gid;
-};
-#endif /* HAVE_UCRED */
/**
* initialize a struct sockaddr_in
int send_bin_buffer(int fd, const char *buf, size_t len)
{
int ret;
+ crypt_function *cf = NULL;
+
+ if (fd <= max_crypt_fd)
+ cf = crypt_functions[2 * fd + 1];
if (!len)
PARA_CRIT_LOG("%s", "len == 0\n");
- if (crypt_function_send) {
+ if (cf) {
unsigned char *outbuf = para_malloc(len);
- crypt_function_send(len, (unsigned char *)buf, outbuf);
+ (*cf)(len, (unsigned char *)buf, outbuf);
ret = sendall(fd, (char *)outbuf, &len);
free(outbuf);
} else
__must_check int recv_bin_buffer(int fd, char *buf, ssize_t size)
{
int n;
+ crypt_function *cf = NULL;
- if (crypt_function_recv) {
+ if (fd <= max_crypt_fd)
+ cf = crypt_functions[2 * fd];
+ if (cf) {
unsigned char *tmp = para_malloc(size);
n = recv(fd, tmp, size, 0);
if (n > 0)
- crypt_function_recv(n, tmp, (unsigned char *)buf);
+ (*cf)(n, tmp, (unsigned char *)buf);
free(tmp);
} else
n = recv(fd, buf, size, 0);
{
int n;
- if ((n = recv_bin_buffer(fd, buf, size - 1)) >= 0)
+ n = recv_bin_buffer(fd, buf, size - 1);
+ if (n >= 0)
buf[n] = '\0';
+ else
+ *buf = '\0';
return n;
}
/**
* wrapper around gethostbyname
*
- * @param host hostname or IPv4 address
- * \return The hostent structure or a NULL pointer if an error occurs
+ * \param host hostname or IPv4 address
+ * \param ret the hostent structure is returned here
+ *
+ * \return positive on success, negative on errors. On success, \a ret
+ * contains the return value of the underlying gethostbyname() call.
+ *
* \sa gethostbyname(2)
*/
-struct hostent *get_host_info(char *host)
+int get_host_info(char *host, struct hostent **ret)
{
PARA_INFO_LOG("getting host info of %s\n", host);
/* FIXME: gethostbyname() is obsolete */
- return gethostbyname(host);
+ *ret = gethostbyname(host);
+ return *ret? 1 : -E_HOST_INFO;
}
/**
return fd;
}
+#ifndef HAVE_UCRED
+ struct ucred {
+ uid_t uid, pid, gid;
+};
+ssize_t send_cred_buffer(int sock, char *buf)
+{
+ return send_buffer(sock, buf);
+}
+int recv_cred_buffer(int fd, char *buf, size_t size)
+{
+ return recv_buffer(fd, buf, size) > 0? 1 : -E_RECVMSG;
+}
+#else /* HAVE_UCRED */
/**
* send NULL terminated buffer and Unix credentials of the current process
*
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);
-#ifdef HAVE_UCRED
/* attach the ucred struct */
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
*(struct ucred *)CMSG_DATA(cmsg) = c;
msg.msg_controllen = cmsg->cmsg_len;
-#endif
ret = sendmsg(sock, &msg, 0);
if (ret < 0)
ret = -E_SENDMSG;
int yes = 1;
struct ucred cred;
-#ifdef HAVE_UCRED
setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &yes, sizeof(int));
-#endif
memset(&msg, 0, sizeof(msg));
memset(buf, 0, size);
iov.iov_base = buf;
msg.msg_controllen = sizeof(control);
if (recvmsg(fd, &msg, 0) < 0)
return -E_RECVMSG;
-#ifdef HAVE_UCRED
result = -E_SCM_CREDENTIALS;
cmsg = CMSG_FIRSTHDR(&msg);
while (cmsg) {
}
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
-#endif
return result;
}
+#endif /* HAVE_UCRED */
/** how many pending connections queue will hold */
#define BACKLOG 10
goto out;
ret = 1;
out:
- free(buf);
if (ret < 0)
- PARA_NOTICE_LOG("did not receive pattern '%s'\n", buf);
+ PARA_NOTICE_LOG("did not receive pattern '%s'\n", pattern);
+ free(buf);
return ret;
}