aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-04-11 18:47:59 +0200
committerHarald Welte <laforge@gnumonks.org>2019-04-11 19:27:17 +0200
commitc2febf9c7343475194d5c3d9d698f8687701aec2 (patch)
treef69849217962c830587b4a0476c00145da58d626
parent19f2d1a76cd348528602f2b4f4cfa46eb1007092 (diff)
ggsn: Add minimalistic PAP support
Some modems are configured to use PAP as an additional authentication mechanism beyond the GSM authentication that's part of GMM. Let's handle such PAP authentication requests by simply acknowledging them all, without actually checking any credentials database. This is the most sane thing we can do for now, without adding external requirements / interfaces like radius servers or the like. Change-Id: I81875f30f9f1497199253497f84718510747f731
-rw-r--r--ggsn/ggsn.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index f46436f..d079efe 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -1,7 +1,7 @@
/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003, 2004 Mondru AB.
- * Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * Copyright (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
*
* The contents of this file may be used under the terms of the GNU
* General Public License Version 2, provided that the above copyright
@@ -47,6 +47,7 @@
#include <osmocom/core/stats.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/timer.h>
+#include <osmocom/core/utils.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_vty.h>
@@ -494,6 +495,64 @@ static struct ippoolm_t *pdp_get_peer_ipv(struct pdp_t *pdp, bool is_ipv6) {
return NULL;
}
+struct pap_element {
+ uint8_t code;
+ uint8_t id;
+ uint16_t len; /* length including header */
+ uint8_t data[0];
+} __attribute__((packed));
+
+enum pap_code {
+ PAP_CODE_AUTH_REQ = 1,
+ PAP_CODE_AUTH_ACK = 2,
+ PAP_CODE_AUTH_NAK = 3,
+};
+
+static const char *pap_welcome = "Welcome to OsmoGGSN";
+
+/* Handle PAP protocol according to RFC 1334 */
+static void process_pco_element_pap(const struct pco_element *pco_in, struct msgb *resp,
+ const struct apn_ctx *apn, struct pdp_t *pdp)
+{
+ const struct pap_element *pap_in = (const struct pap_element *) pco_in->data;
+ unsigned int pap_welcome_len = strlen(pap_welcome);
+ uint8_t pap_out_size = sizeof(struct pap_element) + 1 + pap_welcome_len;
+ struct pap_element *pap_out = alloca(pap_out_size);
+ uint8_t peer_id_len;
+ const uint8_t *peer_id;
+
+ if (sizeof(*pap_in) > pco_in->length)
+ goto ret_broken;
+ if (htons(pap_in->len) > pco_in->length)
+ goto ret_broken;
+
+ switch (pap_in->code) {
+ case PAP_CODE_AUTH_REQ:
+ peer_id_len = pap_in->data[0];
+ peer_id = &pap_in->data[1];
+ LOGPPDP(LOGL_DEBUG, pdp, "PCO PAP PeerId = %s, ACKing\n",
+ osmo_quote_str((const char *)peer_id, peer_id_len));
+ /* Password-Length + Password following here, but we don't care */
+ pap_out->code = PAP_CODE_AUTH_ACK;
+ pap_out->id = pap_in->id;
+ pap_out->len = htons(pap_out_size);
+ pap_out->data[0] = pap_welcome_len;
+ memcpy(pap_out->data+1, pap_welcome, pap_welcome_len);
+ msgb_t16lv_put(resp, PCO_P_PAP, pap_out_size, (uint8_t *) pap_out);
+ break;
+ case PAP_CODE_AUTH_ACK:
+ case PAP_CODE_AUTH_NAK:
+ default:
+ LOGPPDP(LOGL_NOTICE, pdp, "Unsupported PAP PCO Code %u, ignoring\n", pap_in->code);
+ break;
+ }
+ return;
+
+ret_broken:
+ LOGPPDP(LOGL_NOTICE, pdp, "Invalid PAP PCO Length: %s, ignoring\n",
+ osmo_hexdump_nospc((const uint8_t *)pco_in, pco_in->length));
+}
+
static void process_pco_element_ipcp(const struct pco_element *pco_elem, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
@@ -575,6 +634,9 @@ static void process_pco_element(const struct pco_element *pco_elem, struct msgb
const struct apn_ctx *apn, struct pdp_t *pdp)
{
switch (ntohs(pco_elem->protocol_id)) {
+ case PCO_P_PAP:
+ process_pco_element_pap(pco_elem, resp, apn, pdp);
+ break;
case PCO_P_IPCP:
process_pco_element_ipcp(pco_elem, resp, apn, pdp);
break;