diff --git a/kdc/connect.c b/kdc/connect.c
index c0978bb0f..2f4d27037 100644
--- a/kdc/connect.c
+++ b/kdc/connect.c
@@ -261,6 +261,53 @@ handle_tcp(struct descr *d, int index, int min_free)
n = 0;
}
}
+#ifdef HTTP
+ else if(strncmp(d[index].buf, "GET ", 4) == 0 &&
+ strncmp(d[index].buf + d[index].len - 4, "\r\n\r\n", 4) == 0){
+ char *s, *p, *t;
+ void *data;
+ int len;
+ s = d[index].buf;
+ p = strstr(s, "\r\n");
+ *p = 0;
+ p = NULL;
+ kdc_log(5, "HTTP request");
+ strtok_r(s, " \t", &p);
+ t = strtok_r(NULL, " \t", &p);
+ if(t == NULL){
+
+ }
+ data = malloc(strlen(t));
+ len = base64_decode(t, data);
+ if(len < 0){
+ const char *msg =
+ "HTTP/1.1 404 Not found\r\n"
+ "Server: Heimdal/" VERSION "\r\n"
+ "Content-type: text/html\r\n"
+ "Content-transfer-encoding: 8bit\r\n\r\n"
+ "
404 Not found\r\n"
+ "404 Not found
\r\n"
+ "That page doesn't exist, maybe you are looking for "
+ "Heimdal?\r\n";
+ write(d[index].s, msg, strlen(msg));
+ free(data);
+ clear_descr(d + index);
+ return;
+ }
+ {
+ const char *msg =
+ "HTTP/1.1 200 OK\r\n"
+ "Server: Heimdal/" VERSION "\r\n"
+ "Content-type: application/octet-stream\r\n"
+ "Content-transfer-encoding: binary\r\n\r\n";
+ write(d[index].s, msg, strlen(msg));
+ }
+ memcpy(d[index].buf, data, len);
+ d[index].len = len;
+ n = 0;
+ free(data);
+ }
+#endif
if(n == 0){
do_request(d[index].buf, d[index].len,
d[index].s, (struct sockaddr*)&from, from_len);
diff --git a/lib/krb5/send_to_kdc.c b/lib/krb5/send_to_kdc.c
index 0c186568b..7ba08f133 100644
--- a/lib/krb5/send_to_kdc.c
+++ b/lib/krb5/send_to_kdc.c
@@ -55,31 +55,73 @@ send_and_recv (int fd,
if (sendto (fd, send->data, send->length, 0,
(struct sockaddr *)addr, sizeof(*addr)) < 0)
return -1;
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
- timeout.tv_sec = tmout;
- timeout.tv_usec = 0;
- ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
- if (ret <= 0)
- return -1;
- else {
- int len;
+ recv->data = NULL;
+ recv->length = 0;
+ while(1){
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ timeout.tv_sec = tmout;
+ timeout.tv_usec = 0;
+ ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
+ if (ret <= 0)
+ return -1;
+ else {
+ int len;
- if (ioctl (fd, FIONREAD, &nbytes) < 0)
- return -1;
+ if (ioctl (fd, FIONREAD, &nbytes) < 0)
+ return -1;
+ if(nbytes == 0)
+ return 0;
- recv->data = malloc (nbytes);
- ret = recvfrom (fd, recv->data, nbytes, 0, NULL, &len);
- if (ret < 0) {
- free (recv->data);
- return -1;
- }
- recv->data = realloc (recv->data, ret);
- recv->length = ret;
- return 0;
+ recv->data = realloc(recv->data, recv->length + nbytes);
+ ret = recvfrom (fd, recv->data + recv->length, nbytes,
+ 0, NULL, &len);
+ if (ret < 0) {
+ free (recv->data);
+ return -1;
+ }
+ recv->length += ret;
+ }
}
}
+static int
+send_and_recv_http(int fd,
+ time_t tmout,
+ struct sockaddr_in *addr,
+ const krb5_data *send,
+ krb5_data *recv)
+{
+ char *request;
+ char *str;
+ krb5_data r;
+ int ret;
+ int len = base64_encode(send->data, send->length, &str);
+ if(len < 0)
+ return -1;
+ asprintf(&request, "GET %s HTTP/1.1\r\n\r\n", str);
+ free(str);
+ r.data = request;
+ r.length = strlen(request);
+ ret = send_and_recv(fd, tmout, addr, &r, recv);
+ free(request);
+ if(ret)
+ return ret;
+ {
+ char *s, *p;
+ s = realloc(recv->data, recv->length + 1);
+ s[recv->length] = 0;
+ p = strstr(s, "\r\n\r\n");
+ if(p == NULL)
+ return -1;
+ p += 4;
+ recv->data = s;
+ recv->length -= p - s;
+ memmove(recv->data, p, recv->length);
+ }
+ return 0;
+}
+
krb5_error_code
krb5_sendto_kdc (krb5_context context,
const krb5_data *send,
@@ -94,10 +136,6 @@ krb5_sendto_kdc (krb5_context context,
int i;
port = krb5_getportbyname ("kerberos", "udp", htons(88));
- fd = socket (AF_INET, SOCK_DGRAM, 0);
- if (fd < 0) {
- return errno;
- }
err = krb5_get_krbhst (context, realm, &hostlist);
if (err) {
@@ -109,7 +147,12 @@ krb5_sendto_kdc (krb5_context context,
for (hp = hostlist; (p = *hp); ++hp) {
char *addr;
char *colon;
+ int http_flag = 0;
+ if(strncmp(p, "http://", 7) == 0){
+ p += 7;
+ http_flag = 1;
+ }
colon = strchr (p, ':');
if (colon)
*colon = '\0';
@@ -120,7 +163,16 @@ krb5_sendto_kdc (krb5_context context,
*colon++ = ':';
while ((addr = *hostent->h_addr_list++)) {
struct sockaddr_in a;
+ int ret;
+ if(http_flag)
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ else
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if(fd < 0){
+ return errno;
+ }
memset (&a, 0, sizeof(a));
a.sin_family = AF_INET;
if (colon) {
@@ -131,16 +183,22 @@ krb5_sendto_kdc (krb5_context context,
} else
a.sin_port = port;
a.sin_addr = *((struct in_addr *)addr);
+ connect(fd, (struct sockaddr*)&a, sizeof(a));
- if (send_and_recv (fd, context->kdc_timeout,
- &a, send, receive) == 0) {
- close (fd);
- krb5_free_krbhst (context, hostlist);
- return 0;
+ if(http_flag)
+ ret = send_and_recv_http(fd, context->kdc_timeout,
+ &a, send, receive);
+ else
+
+ ret = send_and_recv (fd, context->kdc_timeout,
+ &a, send, receive);
+ close (fd);
+ if(ret == 0){
+ krb5_free_krbhst (context, hostlist);
+ return 0;
}
}
- }
- close (fd);
+ }
krb5_free_krbhst (context, hostlist);
return KRB5_KDC_UNREACH;
}