8
0
Fork 0
historical archive of an early approach towards a stand-alone AUthentication Center. Use osmo-hlr instead.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
osmo-auc/src/auc_map.c

255 lines
6.6 KiB

/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
#include <osmocom/crypt/auth.h>
#include <asn1c/OCTET_STRING.h>
#include <asn1c/der_encoder.h>
#include <osmocom/map/IMSI.h>
#include <osmocom/map/TBCD-STRING.h>
#include <osmocom/map/SendAuthenticationInfoArg.h>
#include <osmocom/map/SendAuthenticationInfoRes.h>
#include <osmocom/map/SendAuthenticationInfoResOld.h>
/* move this to generic osmocom asn1c helper */
asn_enc_rval_t
der_encode_to_msgb(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
struct msgb *msg)
{
asn_enc_rval_t ar;
ar = der_encode_to_buffer(type_descriptor, struct_ptr,
msg->data, msgb_tailroom(msg));
if (ar.encoded > 0)
msgb_put(msg, ar.encoded);
return ar;
}
/* move this to generic osmocom asn1c helper */
int tbcd2char(char *out, unsigned int out_len, const TBCD_STRING_t *oct)
{
char *cur = out;
int i;
for (i = 0; i < oct->size; i++) {
uint8_t inbyte = oct->buf[i];
uint8_t nibble;
nibble = inbyte >> 4;
/* padding should never occur on the first nibble of an octet */
if (nibble == 0xF)
return -EINVAL;
*cur++ = osmo_bcd2char(oct->buf[i] >> 4);
if (cur - out >= out_len)
goto ret;
nibble = inbyte & 0xF;
if (nibble == 0xF)
break;
*cur++ = osmo_bcd2char(oct->buf[i] >> 4);
if (cur - out >= out_len)
goto ret;
}
ret:
out[out_len-1] = '\0';
return cur - out;
}
/* The nesting is as follows:
* SendAuthenticationInfoRes
* AuthenticationSetList
* QuintupletList_t
* AuthenticationQuintuplet
* TripletList_t
* AuthenticationTriplet
*/
static SendAuthenticationInfoRes_t *
make_authinfo_res(void *ctx, const struct osmo_auth_vector *vecs, int num_vecs, int umts)
{
SendAuthenticationInfoRes_t *ai_res;
int i;
ai_res = talloc_zero(ctx, SendAuthenticationInfoRes_t);
ai_res->authenticationSetList = talloc_zero(ai_res, AuthenticationSetList_t);
if (umts) {
ai_res->authenticationSetList->present = AuthenticationSetList_PR_quintupletList;
for (i = 0; i < num_vecs; i++) {
const struct osmo_auth_vector *vec = &vecs[i];
AuthenticationQuintuplet_t *qt;
qt = talloc_zero(ai_res, AuthenticationQuintuplet_t);
OCTET_STRING_fromBuf(&qt->rand, vec->rand, sizeof(vec->rand));
OCTET_STRING_fromBuf(&qt->xres, vec->res, vec->res_len);
OCTET_STRING_fromBuf(&qt->ck, vec->ck, sizeof(vec->ck));
OCTET_STRING_fromBuf(&qt->ik, vec->ik, sizeof(vec->ik));
OCTET_STRING_fromBuf(&qt->autn, vec->autn, sizeof(vec->autn));
asn_sequence_add(&ai_res->authenticationSetList->choice.quintupletList.list, qt);
}
} else {
ai_res->authenticationSetList->present = AuthenticationSetList_PR_tripletList;
for (i = 0; i < num_vecs; i++) {
const struct osmo_auth_vector *vec = &vecs[i];
AuthenticationTriplet_t *t;
t = talloc_zero(ai_res, AuthenticationTriplet_t);
OCTET_STRING_fromBuf(&t->rand, vec->rand, sizeof(vec->rand));
OCTET_STRING_fromBuf(&t->sres, vec->sres, sizeof(vec->sres));
OCTET_STRING_fromBuf(&t->kc, vec->rand, sizeof(vec->kc));
asn_sequence_add(&ai_res->authenticationSetList->choice.tripletList.list, t);
}
}
return ai_res;
}
static SendAuthenticationInfoResOld_t *
make_authinfo_res_old(void *ctx, const struct osmo_auth_vector *vecs, int num_vecs)
{
SendAuthenticationInfoResOld_t *ai_res;
int i;
ai_res = talloc_zero(ctx, SendAuthenticationInfoResOld_t);
for (i = 0; i < num_vecs; i++) {
const struct osmo_auth_vector *vec = &vecs[i];
struct Member *t;
t = talloc_zero(ai_res, struct Member);
OCTET_STRING_fromBuf(&t->rand, vec->rand, sizeof(vec->rand));
OCTET_STRING_fromBuf(&t->sres, vec->sres, sizeof(vec->sres));
OCTET_STRING_fromBuf(&t->kc, vec->rand, sizeof(vec->kc));
asn_sequence_add(&ai_res->list, t);
}
return ai_res;
}
struct msgb *
handle_authinfo_req(void *ctx, const SendAuthenticationInfoArg_t *ai_arg,
int is_v2)
{
struct msgb *msg;
struct osmo_auth_vector vecs[3];
char imsi[15+1];
unsigned int num_vec;
asn_enc_rval_t ar;
int rc;
/* FIXME: decode IMSI */
rc = tbcd2char(imsi, sizeof(imsi), &ai_arg->imsi);
if (rc < 0)
return NULL;
/* don't send more thnan three (our policy) */
num_vec = OSMO_MAX(ai_arg->numberOfRequestedVectors, ARRAY_SIZE(vecs));
/* generate the triplets/quintuplets */
if (ai_arg->re_synchronisationInfo) {
Re_synchronisationInfo_t *res = ai_arg->re_synchronisationInfo;
if (res->rand.size < 16 || res->auts.size < 16)
return NULL;
/* always only one */
num_vec = 1;
rc = auc_gen_vec_auts(vecs, imsi, res->rand.buf, res->auts.buf);
} else
rc = auc_gen_vecs(vecs, imsi, num_vec);
if (rc < 0)
return NULL;
msg = msgb_alloc(1024, "authinfo_res");
if (!msg)
return NULL;
/* actaully encode the response MAP component */
if (!ai_arg->re_synchronisationInfo && is_v2) {
SendAuthenticationInfoResOld_t *ai_res_old;
ai_res_old = make_authinfo_res_old(ctx, vecs, num_vec);
ar = der_encode_to_msgb(&asn_DEF_SendAuthenticationInfoResOld,
ai_res_old, msg);
talloc_free(ai_res_old);
} else {
SendAuthenticationInfoRes_t *ai_res;
int is_umts = 0;
if (vecs[0].auth_types & OSMO_AUTH_TYPE_UMTS)
is_umts = 1;
ai_res = make_authinfo_res(ctx, vecs, num_vec, is_umts);
ar = der_encode_to_msgb(&asn_DEF_SendAuthenticationInfoRes,
ai_res, msg);
talloc_free(ai_res);
}
if (ar.encoded < 0) {
msgb_free(msg);
return NULL;
}
return msg;
}
#if 0
int main(int argc, char **argv)
{
struct osmo_auth_vector vecs[3];
SendAuthenticationInfoRes_t *res;
asn_enc_rval_t ar;
uint8_t buf[1024];
uint32_t buf_len = sizeof(buf);
memset(vecs, 0, sizeof(vecs));
res = make_authinfo_res(NULL, vecs, ARRAY_SIZE(vecs), 1);
if (!res)
exit(1);
ar = der_encode_to_buffer(&asn_DEF_SendAuthenticationInfoRes, res, buf, buf_len);
if (ar.encoded < 0)
exit(2);
buf_len = ar.encoded;
printf("Output: %s\n", osmo_hexdump(buf, buf_len));
//write(1, buf, buf_len);
exit(0);
}
#endif