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
|
/* CGI:IRC C Helper CGI
* Copyright (c) David Leadbeater 2002-2006
* Released Under the GNU GPLv2 or Later
* NO WARRANTY - See GNU GPL for more
* $Id: client.c,v 1.14 2006/05/03 06:51:16 dgl Exp $
*/
/* To compile: cc -O2 -o client.cgi client.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
/* Change this to the tmpfile path set in the CGI:IRC Config */
#define TMPLOCATION "/tmp/cgiirc-"
/******************************************************************************
* Stralloc (from libowfat(-ish))
* If you'd rather use dietlibc/libowfat:
* diet -Os gcc -include stralloc.h -o client.cgi client.c -lowfat */
#ifndef STRALLOC_H
typedef struct stralloc {
char* s;
unsigned long int len;
unsigned long int a;
} stralloc;
int stralloc_ready(stralloc *sa,unsigned long int len) {
register int wanted=len+(len>>3)+30; /* heuristic from djb */
if(!sa->s || sa->a<len) {
register char* tmp;
if (!(tmp=realloc(sa->s,wanted)))
return 0;
sa->a=wanted;
sa->s=tmp;
}
return 1;
}
int stralloc_readyplus(stralloc *sa,unsigned long len) {
if (sa->s) {
if (sa->len + len < len) return 0; /* catch integer overflow */
return stralloc_ready(sa,sa->len+len);
} else
return stralloc_ready(sa,len);
}
int stralloc_catb(stralloc *sa,const char *buf,unsigned long int len) {
if (stralloc_readyplus(sa,len)) {
memcpy(sa->s+sa->len,buf,len);
sa->len+=len;
return 1;
}
return 0;
}
int stralloc_cats(stralloc *sa,const char *buf) {
return stralloc_catb(sa,buf,strlen(buf));
}
int stralloc_cat(stralloc *sa,stralloc *sa2) {
return stralloc_catb(sa,sa2->s,sa2->len);
}
int stralloc_append(stralloc *sa,const char *in) {
if (stralloc_readyplus(sa,1)) {
sa->s[sa->len]=*in;
++sa->len;
return 1;
}
return 0;
}
#define stralloc_0(sa) stralloc_append(sa,"")
#endif
/******************************************************************************/
int unix_connect(stralloc *where);
int error(char *error);
void readinput(stralloc *);
void get_rand(stralloc *, stralloc *);
void get_cookie(stralloc *);
int main(void) {
int fd, sz;
char tmp[2048];
stralloc params = {0}, random = {0}, cookie = {0};
readinput(¶ms);
if(!params.len)
error("No input found");
stralloc_0(¶ms);
get_rand(¶ms, &random);
if(!random.len)
error("Random value not found");
params.len--;
get_cookie(&cookie);
if(cookie.len) {
stralloc_cats(¶ms, "&COOKIE=");
stralloc_cat(¶ms, &cookie);
}
fd = unix_connect(&random);
send(fd, params.s, params.len, 0);
send(fd, "\n", 1, 0);
while((sz = read(fd, tmp, sizeof tmp)) > 0) {
write(STDOUT_FILENO, tmp, sz);
}
return 0;
}
int error(char *error) {
puts("Content-type: text/html\n");
puts("An error occurred:");
puts(error);
exit(1);
}
void readinput(stralloc *input) {
char *method = getenv("REQUEST_METHOD");
if(!method) return;
if(strcmp(method, "GET") == 0) {
char *query = getenv("QUERY_STRING");
if(query)
stralloc_cats(input, query);
}else if(strcmp(method, "POST") == 0) {
int length;
char *ctlength = getenv("CONTENT_LENGTH");
if(!ctlength) return;
length = atoi(ctlength);
// Hopefully noone will need to send more than 5KB
if(length <= 0 || length > (1024*5)) return;
stralloc_ready(input, length);
size_t sz = read(STDIN_FILENO, input->s, length);
if(sz <= 0) return;
input->len = sz;
}
}
void get_rand(stralloc *params, stralloc *random) {
char *ptr = strstr(params->s, "R=");
if(!ptr)
return;
ptr += 2;
while(ptr < params->s + params->len) {
if(!isalpha(*ptr) && !isdigit(*ptr))
break;
stralloc_append(random, ptr++);
}
}
void get_cookie(stralloc *cookie) {
char *httpcookie;
char *sptr, *end_ptr;
httpcookie = getenv("HTTP_COOKIE");
if(!httpcookie) return;
#define COOKIE_NAME "cgiircauth="
sptr = strstr(httpcookie, COOKIE_NAME);
if(sptr == NULL) return;
sptr += strlen(COOKIE_NAME);
if(!*sptr) return;
end_ptr = strchr(sptr, ';');
if(end_ptr == NULL)
end_ptr = sptr + strlen(sptr) - 1;
stralloc_catb(cookie, sptr, 1 + end_ptr - sptr);
}
#ifndef SUN_LEN
#define SUN_LEN(x) (sizeof(*(x)) - sizeof((x)->sun_path) + strlen((x)->sun_path))
#endif
int unix_connect(stralloc *where) {
stralloc filename = {0}, errmsg = {0};
struct sockaddr_un saddr;
int sock;
stralloc_cats(&filename, TMPLOCATION);
stralloc_cat(&filename, where);
stralloc_cats(&filename, "/sock");
stralloc_0(&filename);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if(sock == -1) error("socket() error");
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, filename.s, sizeof(saddr.sun_path));
saddr.sun_path[sizeof(saddr.sun_path) - 1] = '\0';
if(connect(sock, (struct sockaddr *)&saddr, SUN_LEN(&saddr)) == -1) {
stralloc_cats(&errmsg, "connect(): ");
stralloc_cats(&errmsg, strerror(errno));
stralloc_0(&errmsg);
error(errmsg.s);
}
return sock;
}
|