Mercurial > pidgin
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"); |
