The code has not been properly integrated yet. This patch simply adds the required functionality but doesn't use it in any way yet. We now depend on libosmo-asn1-map and libans1c.master
parent
fe0cb4bc58
commit
a4656d703d
@ -0,0 +1,255 @@ |
||||
/* (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 |
Reference in new issue