summaryrefslogtreecommitdiffstats
path: root/gatchat/gatppp.c
diff options
context:
space:
mode:
authorPhilip Paeps <philip@paeps.cx>2014-06-19 12:07:05 +0200
committerDenis Kenzior <denkenz@gmail.com>2014-06-21 11:50:34 -0500
commita88662d23c45f49d9af5a508d4d0a778950b2420 (patch)
tree493246fd2c2789995a6530ca8f379e6a4ed402c8 /gatchat/gatppp.c
parent1dd85809307b200bfe87e6a71c68fa244cb15bc6 (diff)
downloadofono-a88662d23c45f49d9af5a508d4d0a778950b2420.tar.bz2
gatchat: implement PAP authentication
Make the authentication method configurable, CHAP or PAP, defaulting to CHAP (i.e.: previous behaviour). Implementation details: o If PAP is configured, we NAK the CHAP authentication protocol option in LCP configuration requests and suggest PAP instead. This works around the amusing requirement of 3GPP TS 29.061 that modems must send a forced positive acknowledgement of the authentication method tried (i.e.: the modem will successfully accept any CHAP handshake, but if the network only supports PAP, the modem will hang up when it tries and fails to activate the PDP context) o The PAP Authenticate-Request is resent a hard-coded three times at ten-second intervals. This may be a bit too persistent. Chances are if it doesn't work the first time, it'll never work, but the RFC insists that we MUST retry.
Diffstat (limited to 'gatchat/gatppp.c')
-rw-r--r--gatchat/gatppp.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index f767f4a0..e3266efc 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -64,11 +64,13 @@ struct _GAtPPP {
struct pppcp_data *ipcp;
struct ppp_net *net;
struct ppp_chap *chap;
+ struct ppp_pap *pap;
GAtHDLC *hdlc;
gint mru;
gint mtu;
char username[256];
char password[256];
+ GAtPPPAuthMethod auth_method;
GAtPPPConnectFunc connect_cb;
gpointer connect_data;
GAtPPPDisconnectFunc disconnect_cb;
@@ -150,13 +152,15 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol)
return TRUE;
break;
case PPP_PHASE_AUTHENTICATION:
- if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL)
+ if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
+ protocol != PAP_PROTOCOL)
return TRUE;
break;
case PPP_PHASE_DEAD:
return TRUE;
case PPP_PHASE_NETWORK:
if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
+ protocol != PAP_PROTOCOL &&
protocol != IPCP_PROTO)
return TRUE;
break;
@@ -222,6 +226,12 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
case IPCP_PROTO:
pppcp_process_packet(ppp->ipcp, packet, len - offset);
break;
+ case PAP_PROTOCOL:
+ if (ppp->pap)
+ ppp_pap_process_packet(ppp->pap, packet, len - offset);
+ else
+ pppcp_send_protocol_reject(ppp->lcp, buf, len);
+ break;
case CHAP_PROTOCOL:
if (ppp->chap) {
ppp_chap_process_packet(ppp->chap, packet,
@@ -359,6 +369,12 @@ void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
guint16 proto = get_host_short(auth_data);
switch (proto) {
+ case PAP_PROTOCOL:
+ if (ppp->pap)
+ ppp_pap_free(ppp->pap);
+
+ ppp->pap = ppp_pap_new(ppp);
+ break;
case CHAP_PROTOCOL:
if (ppp->chap)
ppp_chap_free(ppp->chap);
@@ -437,10 +453,18 @@ void ppp_ipcp_finished_notify(GAtPPP *ppp)
void ppp_lcp_up_notify(GAtPPP *ppp)
{
- /* Wait for the peer to send us a challenge if we expect auth */
if (ppp->chap != NULL) {
+ /* Wait for the peer to send us a challenge. */
ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
return;
+ } else if (ppp->pap != NULL) {
+ /* Try to send an Authenticate-Request and wait for reply. */
+ if (ppp_pap_start(ppp->pap) == TRUE)
+ ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
+ else
+ /* It'll never work out. */
+ ppp_auth_notify(ppp, FALSE);
+ return;
}
/* Otherwise proceed as if auth succeeded */
@@ -588,6 +612,22 @@ const char *g_at_ppp_get_password(GAtPPP *ppp)
return ppp->password;
}
+gboolean g_at_ppp_set_auth_method(GAtPPP *ppp, GAtPPPAuthMethod method)
+{
+ if (method != G_AT_PPP_AUTH_METHOD_CHAP &&
+ method != G_AT_PPP_AUTH_METHOD_PAP)
+ return FALSE;
+
+ ppp->auth_method = method;
+
+ return TRUE;
+}
+
+GAtPPPAuthMethod g_at_ppp_get_auth_method(GAtPPP *ppp)
+{
+ return ppp->auth_method;
+}
+
void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename)
{
if (ppp == NULL)
@@ -727,6 +767,9 @@ void g_at_ppp_unref(GAtPPP *ppp)
else if (ppp->fd >= 0)
close(ppp->fd);
+ if (ppp->pap)
+ ppp_pap_free(ppp->pap);
+
if (ppp->chap)
ppp_chap_free(ppp->chap);
@@ -794,6 +837,9 @@ static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip)
/* initialize IPCP state */
ppp->ipcp = ipcp_new(ppp, is_server, ip);
+ /* chap authentication by default */
+ ppp->auth_method = G_AT_PPP_AUTH_METHOD_CHAP;
+
return ppp;
}