diff --git a/c/httphead/httphead.c b/c/httphead/httphead.c index a498dff..f446d8d 100644 --- a/c/httphead/httphead.c +++ b/c/httphead/httphead.c @@ -36,15 +36,19 @@ #include #include +// for debugging only +#include + const char usagemsg[] = - "usage: httphead [-r] [-q] [-p port] [-s host] [-d path] [-s host] URL\n" + "usage: httphead [-r] [-q] [-u username:password] [-p port] [-s host] [-d path] [-s host] URL\n" "\n" "options:\n" - " -p port use this port instead of 80\n" - " -s host use this host instead of the one specified in the URL\n" - " -d path use this path instead of the one specified in the URL\n" - " -r show sent request\n" - " -q show only the recieved status code\n" + " -p port use this port instead of 80\n" + " -s host use this host instead of the one specified in the URL\n" + " -d path use this path instead of the one specified in the URL\n" + " -u user:passwd authenticate using a username and a password\n" + " -r show sent request\n" + " -q show only the recieved status code\n" " also: -v show version\n" " -h display this help\n" " -l display (BSD) license\n" @@ -77,7 +81,9 @@ "THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" ; -const char versionmsg[] = "httphead 0.2\n"; +const char versionmsg[] = "httphead 0.3\n"; + +const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define HH_BUFFSIZE 512 @@ -85,17 +91,21 @@ void license ( ); void version ( ); -void showerror ( char* type ); +void showerror ( const char* type ); void crlf ( int s ); -char* gethost ( char* url ); -char* getpath ( char* url ); -char* getstatuscode ( char* response ); +char* getuser ( const char* url ); +char* getpassword ( const char* url ); +char* gethost ( const char* url ); +char* getpath ( const char* url ); +char* getstatuscode ( const char* response ); +char* b64 ( const char* str ); int main ( int argc, char* argv[] ) { int tmp; + int l; char* hend = NULL; char buff[HH_BUFFSIZE+1]; @@ -103,18 +113,21 @@ char* host = NULL; char* path = NULL; + char* username = NULL; + char* password = NULL; int port = 80; int showrequest = 0; int statuscodeonly = 0; char* statuscode = NULL; + char* authstring = NULL; struct hostent *remote_hostent = NULL; struct sockaddr_in *remote_host_addr = NULL; int sock; - while ( (tmp = getopt(argc, argv, "qrd:s:p:hlv")) != -1 ) { + while ( (tmp = getopt(argc, argv, "u:qrd:s:p:hlv")) != -1 ) { switch ( tmp ) { case 'h': usage(); @@ -140,6 +153,23 @@ case 'r': showrequest = 1; break; + case 'u': + username = optarg; + + if ((password = strchr(username, ':')) == username) { + username = NULL; + } + + if (password != NULL) { + *password = '\0'; + + if (*(password+1) != '\0') { + password++; + } else { + password = NULL; + } + } + break; } } @@ -158,6 +188,37 @@ host = gethost(url); } + if ( username == NULL ) { + username = getuser(url); + } + + if ( password == NULL ) { + password = getpassword(url); + } + + if ((username != NULL) || (password != NULL)) { + tmp = 0; + if ( username != NULL ) { + l = strlen(username); + tmp += l; + } + tmp++; + + if ( password != NULL ) { + tmp += strlen(password); + } + + authstring = (char*)alloca(sizeof(char)*(tmp+1)); + + memcpy(authstring, username, l); + authstring[l] = ':'; + memcpy(authstring+l+1, password, strlen(password)); + + authstring[tmp] = '\0'; + + authstring = b64(authstring); + } + remote_hostent = gethostbyname(host); if ( remote_hostent == NULL ) { @@ -190,8 +251,14 @@ crlf(1); write(1, "Host: ", 6); write(1, host, strlen(host)); - crlf(1); + + if ((username != NULL) || (password != NULL)) { + write(1, "Authorization: Basic ", 21); + write(1, authstring, strlen(authstring)); + crlf(1); + } + crlf(1); write(1, "Response:\n\n", 12); @@ -203,8 +270,14 @@ crlf(sock); write(sock, "Host: ", 6); write(sock, host, strlen(host)); - crlf(sock); + + if ((username != NULL) || (password != NULL)) { + write(sock, "Authorization: Basic ", 21); + write(sock, authstring, strlen(authstring)); + crlf(sock); + } + crlf(sock); while ( (tmp = recv(sock, buff, HH_BUFFSIZE, 0)) > 0 ) { @@ -244,7 +317,7 @@ exit(0); } -char* _gethoststart ( char* url ) { +char* _gethoststart ( const char* url ) { char* s = NULL; s = strstr(url, "http://"); @@ -266,7 +339,7 @@ return s; } -int _gethostlen ( char* s ) { +int _gethostlen ( const char* s ) { int e = 0; while ( *(s+e) != '/' && *(s+e) != '?' && *(s+e) != '\0' ) { @@ -276,7 +349,7 @@ return e; } -char* getstatuscode ( char* s ) { +char* getstatuscode ( const char* s ) { char* htp = NULL; if ( (htp = strstr(s, "HTTP/")) != NULL ) { @@ -296,7 +369,7 @@ return htp; } -char* getpath ( char* url ) { +char* getpath ( const char* url ) { char* s = NULL; int e; @@ -315,10 +388,79 @@ return s; } -char* gethost ( char* url ) { +char* getpassword ( const char* url ) { char* s = NULL; char* r = NULL; int e = 0; + int a = 0; + int p = 0; + + s = _gethoststart(url); + + e = _gethostlen(s); + + a = strchr(s, '@'); + + if ((a == NULL) || (a >= s+e)) { + return NULL; + } + + p = strchr(s, ':'); + + if ((p == NULL) || (p >= a-1)) { + return NULL; + } + + r = (char*)malloc(sizeof(char)*(a - p)); + + memcpy(r, p+1, (a - p - 1)); + + r[a-p] = '\0'; + + return r; +} + +char* getuser ( const char* url ) { + char* s = NULL; + char* r = NULL; + int e = 0; + int a = 0; + int p = 0; + + s = _gethoststart(url); + + e = _gethostlen(s); + + a = strchr(s, '@'); + + if ((a == NULL) || (a >= s+e)) { + return NULL; + } + + p = strchr(s, ':'); + + if ((p == NULL) || (p >= s+e)) { + return NULL; + } + + if (p > a) { + p = a; + } + + r = (char*)malloc(sizeof(char)*(1 + (int)p - (int)s)); + + memcpy(r, s, (int)p-(int)s); + + r[1+(int)p-(int)s] = '\0'; + + return r; +} + +char* gethost ( const char* url ) { + char* s = NULL; + char* r = NULL; + int e = 0; + int a = 0; s = _gethoststart(url); @@ -328,6 +470,13 @@ return NULL; } + a = strchr(s, '@'); + + if ((a != NULL) && (a < s+e)) { + e = ((int)(s+e) - (int)a - 2); + s = a+1; + } + r = (char*)malloc(sizeof(char)*(e+1)); memcpy(r, s, e); @@ -337,6 +486,55 @@ return r; } +void _b64_43 ( char* dst, const char* src ) { + dst[0] = b64chars[src[0] >> 2]; + dst[1] = b64chars[(((src[0] & 0x03) << 4) & 0xF0) | (src[1] >> 4)]; + dst[2] = b64chars[((src[1] << 2) & 0x3C) | ((src[2] >> 6) & 0x03)]; + dst[3] = b64chars[src[2] & 0x3F]; +} + +char* b64 ( const char* str ) { + int l = strlen(str); + char* out = NULL; + int pos = 0; + int nl; + + if ( l%3 == 0 ) { + nl = (l/3)*4; + } else { + nl = ((l+(3-(l%3)))/3)*4; + } + + out = (char*)malloc(sizeof(char)*(nl+1)); + out[nl] = '\0'; + + for ( pos = 0; pos < (nl/4)-1; pos++ ) { + _b64_43(out + pos*4, str + pos*3); + } + + if ( l%3 == 0 ) { + _b64_43(out + (nl/4 - 1)*4, str + (nl/4 - 1)*3); + } + + if ((l%3) == 2 ) { + out[nl-4] = b64chars[str[l-2] >> 2]; + out[nl-3] = b64chars[(((str[l-2] & 0x03) << 4) & 0xF0) | (str[l-1] >> 4)]; + out[nl-2] = b64chars[((str[l-1] << 2) & 0x3C)]; + out[nl-1] = '='; + } + + if ((l%3) == 1 ) { + out[nl-4] = b64chars[str[l-2] >> 2]; + out[nl-3] = b64chars[(((str[l-2] & 0x03) << 4) & 0xF0)]; + out[nl-2] = '='; + out[nl-1] = '='; + } + + out[nl] = '\0'; + + return out; +} + void crlf ( int s ) { write(s, "\x0D\x0A", 2); } @@ -353,7 +551,7 @@ write(1, versionmsg, strlen(versionmsg)); } -void showerror ( char* type ) { +void showerror ( const char* type ) { char* errstr = strerror(errno); write(2, type, strlen(type)); write(2, ": ", 2);