strongswan/src/libcharon/plugins/osmo_epdg/osmo_epdg_utils.c

132 lines
2.5 KiB
C

/*
* Copyright (C) 2023 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Alexander Couzens <acouzens@sysmocom.de>
*
* SPDX-License-Identifier: GPL-2.0+
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <errno.h>
#include <ctype.h>
#include <osmocom/core/msgb.h>
#include <sa/ike_sa.h>
#include <utils/utils.h>
#include <utils/debug.h>
#include "osmo_epdg_utils.h"
struct msgb *chunk_to_msgb(chunk_t *chunk)
{
struct msgb *msg;
if (chunk->len < sizeof(*msg))
{
return NULL;
}
msg = (struct msgb *) chunk->ptr;
memset(msg, 0x00, sizeof(*msg));
msg->data_len = chunk->len - sizeof(*msg);
msg->len = 0;
msg->data = msg->_data;
msg->head = msg->_data;
msg->tail = msg->_data;
return msg;
}
int get_imsi_ike(ike_sa_t *ike_sa, char *imsi, size_t imsi_len)
{
identification_t *imsi_id = ike_sa->get_other_id(ike_sa);
if (!imsi_id)
{
return -1;
}
return get_imsi(imsi_id, imsi, imsi_len);
}
int get_imsi(identification_t *id, char *imsi, size_t imsi_len)
{
chunk_t nai = id->get_encoding(id);
/* TODO: maybe use regex? */
/* 099942123456789@mnc042.mcc999.3gpp... */
if (nai.len < 17)
{
DBG1(DBG_NET, "epdg: Invalid NAI %s.", nai);
return -EINVAL;
}
if (nai.ptr[0] != '0')
{
DBG1(DBG_NET, "epdg: Invalid NAI. Only support IMSI (starting with 0). %s.",
nai);
return -EINVAL;
}
strncpy(imsi, nai.ptr + 1, min(15, imsi_len));
return 0;
}
int validate_imsi(const char *imsi)
{
if (!imsi)
return 1;
if (strlen(imsi) != 15)
return 1;
for (int i=0; i<strlen(imsi); i++)
{
if (!isdigit(imsi[i]))
{
return 1;
}
}
return 0;
}
int validate_apn(const char *apn)
{
/* don't support empty apn */
if (!apn)
return 1;
if (!strlen(apn))
return 1;
return 0;
}
int get_apn(ike_sa_t *sa, char *apn, size_t apn_len)
{
identification_t* apn_id;
chunk_t apn_chunk;
apn_id = sa->get_my_id(sa);
if (!apn_id)
{
return -EINVAL;
}
apn_chunk = apn_id->get_encoding(apn_id);
if (apn_chunk.len >= apn_len)
{
return -ENOMEM;
}
memcpy(apn, apn_chunk.ptr, apn_chunk.len);
apn[apn_chunk.len] = 0;
return 0;
}