comparison src/proxy.c @ 12391:804e335b7b62

[gaim-migrate @ 14698] This is NTLM authentication for HTTP proxies, contributed by Thomas Butter with testing and bugfixing by Praveen Karadakal. committer: Tailor Script <tailor@pidgin.im>
author Ethan Blanton <elb@pidgin.im>
date Thu, 08 Dec 2005 03:28:42 +0000
parents 9ed903d0c619
children a88ca6da0b38
comparison
equal deleted inserted replaced
12390:dca3779701a7 12391:804e335b7b62
31 31
32 #include "internal.h" 32 #include "internal.h"
33 #include "cipher.h" 33 #include "cipher.h"
34 #include "debug.h" 34 #include "debug.h"
35 #include "notify.h" 35 #include "notify.h"
36 #include "ntlm.h"
36 #include "prefs.h" 37 #include "prefs.h"
37 #include "proxy.h" 38 #include "proxy.h"
38 #include "util.h" 39 #include "util.h"
39 40
40 static GaimProxyInfo *global_proxy_info = NULL; 41 static GaimProxyInfo *global_proxy_info = NULL;
1049 static void 1050 static void
1050 http_canread(gpointer data, gint source, GaimInputCondition cond) 1051 http_canread(gpointer data, gint source, GaimInputCondition cond)
1051 { 1052 {
1052 int nlc = 0; 1053 int nlc = 0;
1053 int pos = 0; 1054 int pos = 0;
1054 int minor, major, status, error=0; 1055 int minor, major, status = 0, error=0;
1055 struct PHB *phb = data; 1056 struct PHB *phb = data;
1056 char inputline[8192], *p; 1057 char inputline[8192], *p;
1057 1058
1058 gaim_input_remove(phb->inpa);
1059 1059
1060 while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) { 1060 while ((pos < sizeof(inputline)-1) && (nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) {
1061 if (inputline[pos - 1] == '\n') 1061 if (inputline[pos - 1] == '\n')
1062 nlc++; 1062 nlc++;
1063 else if (inputline[pos - 1] != '\r') 1063 else if (inputline[pos - 1] != '\r')
1080 error = (*p!=' '); 1080 error = (*p!=' ');
1081 } 1081 }
1082 } 1082 }
1083 } 1083 }
1084 1084
1085 /* Read the contents */
1086 p = g_strrstr(inputline, "Content-Length: ");
1087 if(p>0) {
1088 gchar *tmp;
1089 int len = 0;
1090 char tmpc;
1091 p += strlen("Content-Length: ");
1092 tmp = strchr(p, '\r');
1093 *tmp = 0;
1094 len = atoi(p);
1095 *tmp = '\r';
1096 while(len--) read(source, &tmpc, 1);
1097 }
1085 if(error) { 1098 if(error) {
1086 gaim_debug_error("proxy", 1099 gaim_debug_error("proxy",
1087 "Unable to parse proxy's response: %s\n", inputline); 1100 "Unable to parse proxy's response: %s\n", inputline);
1088 close(source); 1101 close(source);
1089 source=-1; 1102 source=-1;
1090 } 1103 }
1091 else if(status!=200) { 1104 else if(status!=200) {
1092 gaim_debug_error("proxy", 1105 gaim_debug_error("proxy",
1093 "Proxy server replied with:\n%s\n", p); 1106 "Proxy server replied with:\n%s\n", inputline);
1094 close(source);
1095 source = -1;
1096 1107
1097 /* XXX: why in the hell are we calling gaim_connection_error() here? */ 1108 /* XXX: why in the hell are we calling gaim_connection_error() here? */
1109 if ( status == 407 /* Proxy Auth */ ) {
1110 gchar *ntlm;
1111 if( (ntlm = g_strrstr(inputline, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */
1112 gchar *nonce = ntlm;
1113 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi);
1114 gchar *username;
1115 gchar *request;
1116 gchar *response;
1117 if(!(username = strchr(domain, '\\'))) {
1118 char *msg = g_strdup_printf(_("Proxy connection error %d"), status);
1119 close(source);
1120 source = -1;
1121 gaim_connection_error(phb->account->gc, msg);
1122 g_free(msg);
1123 gaim_input_remove(phb->inpa);
1124 return;
1125 }
1126 *username = 0;
1127 username ++;
1128 ntlm += strlen("Proxy-Authenticate: NTLM ");
1129 while(*nonce != '\r' && *nonce != '\0') nonce ++;
1130 *nonce = 0;
1131 nonce = gaim_ntlm_parse_type2(ntlm);
1132 response = gaim_ntlm_gen_type3(username, (gchar*)gaim_proxy_info_get_password(phb->gpi), (gchar*)gaim_proxy_info_get_host(phb->gpi), domain, nonce);
1133 username--;
1134 *username = '\\';
1135 request = g_strdup_printf("CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\nProxy-Authorization: NTLM %s\r\nProxy-Connection: Keep-Alive\r\n\r\n",
1136 phb->host, phb->port, phb->host, phb->port,
1137 response);
1138 write(source, request, strlen(request));
1139 g_free(request);
1140 g_free(response);
1141 return;
1142 } else if((ntlm = g_strrstr(inputline, "Proxy-Authenticate: NTLM"))) { /* Empty message */
1143 gchar request[2048];
1144 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi);
1145 gchar *username;
1146 int request_len;
1147 if(!(username = strchr(domain, '\\'))) {
1148 char *msg = g_strdup_printf(_("Proxy connection error %d"), status);
1149 close(source);
1150 source = -1;
1151 gaim_connection_error(phb->account->gc, msg);
1152 g_free(msg);
1153 gaim_input_remove(phb->inpa);
1154 return;
1155 }
1156 *username = 0;
1157
1158 request_len = g_snprintf(request, sizeof(request),
1159 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n",
1160 phb->host, phb->port, phb->host, phb->port);
1161
1162 g_return_if_fail(request_len < sizeof(request));
1163 request_len += g_snprintf(request + request_len,
1164 sizeof(request) - request_len,
1165 "Proxy-Authorization: NTLM %s\r\nProxy-Connection: Keep-Alive\r\n\r\n", gaim_ntlm_gen_type1((gchar*)gaim_proxy_info_get_host(phb->gpi),domain));
1166 *username = '\\';
1167 write(source, request, request_len);
1168 return;
1169 } else {
1170 char *msg = g_strdup_printf(_("Proxy connection error %d"), status);
1171 close(source);
1172 source = -1;
1173 gaim_connection_error(phb->account->gc, msg);
1174 g_free(msg);
1175 }
1176 }
1098 if ( status == 403 /* Forbidden */ ) { 1177 if ( status == 403 /* Forbidden */ ) {
1099 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); 1178 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port);
1100 gaim_connection_error(phb->account->gc, msg); 1179 gaim_connection_error(phb->account->gc, msg);
1101 g_free(msg); 1180 g_free(msg);
1102 } else { 1181 } else {
1103 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); 1182 char *msg = g_strdup_printf(_("Proxy connection error %d"), status);
1104 gaim_connection_error(phb->account->gc, msg); 1183 gaim_connection_error(phb->account->gc, msg);
1105 g_free(msg); 1184 g_free(msg);
1106 } 1185 }
1107
1108 } else { 1186 } else {
1109 http_complete(phb, source); 1187 http_complete(phb, source);
1110 } 1188 }
1111 1189
1190 gaim_input_remove(phb->inpa);
1112 return; 1191 return;
1113 } 1192 }
1114 1193
1115 static void 1194 static void
1116 http_canwrite(gpointer data, gint source, GaimInputCondition cond) 1195 http_canwrite(gpointer data, gint source, GaimInputCondition cond)
1147 gaim_proxy_info_get_password(phb->gpi) ? 1226 gaim_proxy_info_get_password(phb->gpi) ?
1148 gaim_proxy_info_get_password(phb->gpi) : ""); 1227 gaim_proxy_info_get_password(phb->gpi) : "");
1149 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); 1228 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1));
1150 g_free(t1); 1229 g_free(t1);
1151 g_return_if_fail(request_len < sizeof(request)); 1230 g_return_if_fail(request_len < sizeof(request));
1231
1152 request_len += g_snprintf(request + request_len, 1232 request_len += g_snprintf(request + request_len,
1153 sizeof(request) - request_len, 1233 sizeof(request) - request_len,
1154 "Proxy-Authorization: Basic %s\r\n", t2); 1234 "Proxy-Authorization: NTLM %s\r\nProxy-Authorization: Basic %s\r\nProxy-Connection: Keep-Alive\r\n", gaim_ntlm_gen_type1((gchar*)gaim_proxy_info_get_host(phb->gpi),""), t2);
1155 g_free(t2); 1235 g_free(t2);
1156 } 1236 }
1157 1237
1158 g_return_if_fail(request_len < sizeof(request)); 1238 g_return_if_fail(request_len < sizeof(request));
1159 strcpy(request + request_len, "\r\n"); 1239 strcpy(request + request_len, "\r\n");