Skip to content

Commit

Permalink
Merge branch 'master' into EAP_AKA_API
Browse files Browse the repository at this point in the history
  • Loading branch information
nickvsnetworking authored Nov 28, 2023
2 parents a74de0a + 4a60f8a commit b5fd292
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 114 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added CORS headers: [Zarya/171](https://github.com/nickvsnetworking/pyhss/pull/171)
- Gx RAR now dynamically creates TFT up to 512k based on UE request.
- SQN Resync now propogates via Geored when enabled
- Renamed sh_profile to xcap_profile in ims_subscriber

### Fixed

Expand All @@ -25,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Optional immediateReattach parameter in Request_16777251_317, via CLR-Flags
- Sh-IMS-Data and IMSPrivateUserIdentity to default_sh_user_data.xml
- Optional config parameter `api.enable_insecure_auc` to allow retrieval of AuC keys through API
- sh_template_path in ims_subscriber

## [1.0.0] - 2023-09-27

Expand Down
5 changes: 0 additions & 5 deletions default_sh_user_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,4 @@
<IMSUserState>{{ Sh_template_vars['imsUserState'] }}</IMSUserState>
</Sh-IMS-Data>

<!-- This container for the XCAP Data for the Subscriber -->

<!-- XCAP data from Database -->
{{ Sh_template_vars['sh_profile'] }}

</Sh-Data>
2 changes: 1 addition & 1 deletion docs/provisioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,6 @@ curl -X 'PUT' \
"msisdn_list": "12341235",
"imsi": "001010000000002",
"ifc_path": "string",
"sh_profile": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><simservs>Your XCAP Data...</simservs>"
"xcap_profile": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><simservs>Your XCAP Data...</simservs>"
}'
```
16 changes: 9 additions & 7 deletions lib/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,23 +184,26 @@ class SERVING_APN(Base):
last_modified = Column(String(100), default=datetime.datetime.now(tz=timezone.utc), doc='Timestamp of last modification')
operation_logs = relationship("SERVING_APN_OPERATION_LOG", back_populates="serving_apn")

# Legacy support for sh_profile. sh_profile is deprecated as of v1.0.1.
class IMS_SUBSCRIBER(Base):
__tablename__ = 'ims_subscriber'
ims_subscriber_id = Column(Integer, primary_key = True, doc='Unique ID of IMS_Subscriber entry')
msisdn = Column(String(18), unique=True, doc=SUBSCRIBER.msisdn.doc)
msisdn_list = Column(String(1200), doc='Comma Separated list of additional MSISDNs for Subscriber')
imsi = Column(String(18), unique=False, doc=SUBSCRIBER.imsi.doc)
ifc_path = Column(String(18), doc='Path to template file for the Initial Filter Criteria')
ifc_path = Column(String(512), doc='Path to template file for the Initial Filter Criteria')
pcscf = Column(String(512), doc='Proxy-CSCF serving this subscriber')
pcscf_realm = Column(String(512), doc='Realm of PCSCF')
pcscf_active_session = Column(String(512), doc='Session Id for the PCSCF when in a call')
pcscf_timestamp = Column(DateTime, doc='Timestamp of last ue attach to PCSCF')
pcscf_peer = Column(String(512), doc='Diameter peer used to reach PCSCF')
sh_profile = Column(Text(12000), doc='Sh Subscriber Profile')
pcscf_peer = Column(String(512), doc='Diameter peer used to reach PCSCF')
xcap_profile = Column(Text(12000), doc='XCAP Subscriber Profile')
sh_profile = Column(Text(12000), doc='Deprecated - XCAP Subscriber Profile')
scscf = Column(String(512), doc='Serving-CSCF serving this subscriber')
scscf_timestamp = Column(DateTime, doc='Timestamp of last ue attach to SCSCF')
scscf_realm = Column(String(512), doc='Realm of SCSCF')
scscf_peer = Column(String(512), doc='Diameter peer used to reach SCSCF')
scscf_peer = Column(String(512), doc='Diameter peer used to reach SCSCF')
sh_template_path = Column(String(512), doc='Path to template file for the Sh Profile')
last_modified = Column(String(100), default=datetime.datetime.now(tz=timezone.utc), doc='Timestamp of last modification')
operation_logs = relationship("IMS_SUBSCRIBER_OPERATION_LOG", back_populates="ims_subscriber")

Expand Down Expand Up @@ -2465,9 +2468,8 @@ def get_device_info_from_TAC(self, imei) -> dict:
"msisdn": newObj['msisdn'],
"msisdn_list": newObj['msisdn'],
"imsi": subscriber_json['imsi'],
"ifc_path" : "default_ifc.xml",
"sh_profile" : "default_sh_user_data.xml"
}
"ifc_path" : "default_ifc.xml"
}
print(ims_subscriber_json)
newObj = database.CreateObj(IMS_SUBSCRIBER, ims_subscriber_json)
print(newObj)
Expand Down
91 changes: 51 additions & 40 deletions lib/diameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2207,47 +2207,60 @@ def Answer_16777217_306(self, packet_vars, avps):
msisdn = None
imsi = None
scscf = None
username = None
try:
user_identity_avp = self.get_avp_data(avps, 700)[0]
msisdn = self.get_avp_data(user_identity_avp, 701)[0] #Get MSISDN from AVP in request
self.logTool.log(service='HSS', level='debug', message="Got raw MSISDN with value " + str(msisdn), redisClient=self.redisMessaging)
msisdn = self.TBCD_decode(msisdn)
self.logTool.log(service='HSS', level='debug', message="Got MSISDN with value " + str(msisdn), redisClient=self.redisMessaging)
except:
self.logTool.log(service='HSS', level='error', message="No MSISDN", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="No MSISDN", redisClient=self.redisMessaging)
try:
username = self.get_avp_data(avps, 601)[0]
except Exception as e:
self.logTool.log(service='HSS', level='error', message="No Username", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="No Username", redisClient=self.redisMessaging)

if msisdn is not None:
self.logTool.log(service='HSS', level='debug', message="Getting susbcriber IMS info based on MSISDN", redisClient=self.redisMessaging)
subscriber_ims_details = self.database.Get_IMS_Subscriber(msisdn=msisdn)
self.logTool.log(service='HSS', level='debug', message="Got subscriber IMS details: " + str(subscriber_ims_details), redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting susbcriber info based on MSISDN", redisClient=self.redisMessaging)
subscriber_details = self.database.Get_Subscriber(msisdn=msisdn)
imsi = subscriber_details.get('imsi', None)
scscf = subscriber_ims_details.get('scscf', None)
if scscf is not None:
imsUserState = 1
else:
imsUserState = 0
self.logTool.log(service='HSS', level='debug', message="Got subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)
subscriber_details = {**subscriber_details, **subscriber_ims_details, 'imsUserState': imsUserState}
self.logTool.log(service='HSS', level='debug', message="Merged subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber IMS info based on MSISDN", redisClient=self.redisMessaging)
try:
subscriber_ims_details = self.database.Get_IMS_Subscriber(msisdn=msisdn)
self.logTool.log(service='HSS', level='debug', message="Got subscriber IMS details: " + str(subscriber_ims_details), redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber info based on MSISDN", redisClient=self.redisMessaging)
subscriber_details = self.database.Get_Subscriber(msisdn=msisdn)
imsi = subscriber_details.get('imsi', None)
scscf = subscriber_ims_details.get('scscf', None)
if scscf is not None:
imsUserState = 1
else:
imsUserState = 0
self.logTool.log(service='HSS', level='debug', message="Got subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)
subscriber_details = {**subscriber_details, **subscriber_ims_details, 'imsUserState': imsUserState}
self.logTool.log(service='HSS', level='debug', message="Merged subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)
except Exception as e:
self.logTool.log(service='HSS', level='debug', message=f"No subscriber found for MSISDN {msisdn}", redisClient=self.redisMessaging)
result_code = 5001
#Experimental Result AVP
avp_experimental_result = ''
avp_experimental_result += self.generate_vendor_avp(266, 40, 10415, '') #AVP Vendor ID
avp_experimental_result += self.generate_avp(298, 40, self.int_to_hex(result_code, 4)) #AVP Experimental-Result-Code
avp += self.generate_avp(297, 40, avp_experimental_result) #AVP Experimental-Result(297)
response = self.generate_diameter_packet("01", "40", 306, 16777217, packet_vars['hop-by-hop-identifier'], packet_vars['end-to-end-identifier'], avp) #Generate Diameter packet
return response
else:
self.logTool.log(service='HSS', level='error', message="No MSISDN or IMSI in Answer_16777217_306() input", redisClient=self.redisMessaging)
self.redisMessaging.sendMetric(serviceName='diameter', metricName='prom_diam_auth_event_count',
metricType='counter', metricAction='inc',
metricValue=1.0,
metricLabels={
"diameter_application_id": 16777216,
"diameter_cmd_code": 306,
"event": "Unknown User",
"imsi_prefix": str(username[0:6])},
metricHelp='Diameter Authentication related Counters',
metricExpiry=60)
result_code = 5005
self.logTool.log(service='HSS', level='error', message="No MSISDN or IMSI in Sh User-Data-Answer input", redisClient=self.redisMessaging)
if username is not None:
self.redisMessaging.sendMetric(serviceName='diameter', metricName='prom_diam_auth_event_count',
metricType='counter', metricAction='inc',
metricValue=1.0,
metricLabels={
"diameter_application_id": 16777216,
"diameter_cmd_code": 306,
"event": "Unknown User",
"imsi_prefix": str(username[0:6])},
metricHelp='Diameter Authentication related Counters',
metricExpiry=60)
result_code = 5001
#Experimental Result AVP
avp_experimental_result = ''
avp_experimental_result += self.generate_vendor_avp(266, 40, 10415, '') #AVP Vendor ID
Expand All @@ -2274,7 +2287,7 @@ def Answer_16777217_306(self, packet_vars, avps):
subscriber_details['mcc'] = self.MCC.zfill(3)

self.logTool.log(service='HSS', level='debug', message="Rendering template with values: " + str(subscriber_details), redisClient=self.redisMessaging)
xmlbody = template.render(Sh_template_vars=subscriber_details) # this is where to put args to the template renderer
xmlbody = template.render(Sh_template_vars=subscriber_details)
avp += self.generate_vendor_avp(702, "c0", 10415, str(binascii.hexlify(str.encode(xmlbody)),'ascii'))

avp += self.generate_avp(268, 40, "000007d1") #DIAMETER_SUCCESS
Expand All @@ -2300,7 +2313,7 @@ def Answer_16777217_307(self, packet_vars, avps):
#Push updated User Data into IMS Backend
#Start with the Current User Data
subscriber_ims_details = self.database.Get_IMS_Subscriber(imsi=imsi)
self.database.UpdateObj(self.database.IMS_SUBSCRIBER, {'sh_profile': sh_user_data}, subscriber_ims_details['ims_subscriber_id'])
self.database.UpdateObj(self.database.IMS_SUBSCRIBER, {'xcap_profile': sh_user_data}, subscriber_ims_details['ims_subscriber_id'])

avp = '' #Initiate empty var AVP #Session-ID
session_id = self.get_avp_data(avps, 263)[0] #Get Session-ID
Expand Down Expand Up @@ -2426,13 +2439,12 @@ def Answer_16777236_265(self, packet_vars, avps):
pass

"""
The below charging rule needs to be replaced by the following logic:
The below logic is applied:
1. Grab the Flow Rules and bitrates from the PCSCF in the AAR,
2. Compare it to a given backup rule
- If the flowrates are greater than the backup rule (UE is asking for more than allowed), use the backup rule
- If the flowrates are lesser than the backup rule, use the requested flowrates. This will allow for better utilization of radio resources.
3. Maybe something to do with the TFT's
4. Send the winning rule.
- If the flowrates are lesser than the backup rule, use the requested flowrates.
3. Send the winning rule.
"""

chargingRule = {
Expand Down Expand Up @@ -2783,11 +2795,11 @@ def Answer_16777291_8388622(self, packet_vars, avps):

try:
if imsi is not None:
self.logTool.log(service='HSS', level='debug', message="Getting susbcriber location based on IMSI", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber location based on IMSI", redisClient=self.redisMessaging)
subscriber_details = self.database.Get_Subscriber(imsi=imsi)
self.logTool.log(service='HSS', level='debug', message="Got subscriber_details from IMSI: " + str(subscriber_details), redisClient=self.redisMessaging)
elif msisdn is not None:
self.logTool.log(service='HSS', level='debug', message="Getting susbcriber location based on MSISDN", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber location based on MSISDN", redisClient=self.redisMessaging)
subscriber_details = self.database.Get_Subscriber(msisdn=msisdn)
self.logTool.log(service='HSS', level='debug', message="Got subscriber_details from MSISDN: " + str(subscriber_details), redisClient=self.redisMessaging)
except Exception as E:
Expand Down Expand Up @@ -3287,6 +3299,7 @@ def Request_16777217_306(self, **kwargs):

if "msisdn" in kwargs:
msisdn = kwargs['msisdn']
msisdn = msisdn.replace('+', '')
msisdn_avp = self.generate_vendor_avp(701, 'c0', 10415, self.TBCD_encode(str(msisdn))) #MSISDN
avp += self.generate_vendor_avp(700, "c0", 10415, msisdn_avp) #User-Identity
avp += self.generate_vendor_avp(701, 'c0', 10415, self.TBCD_encode(str(msisdn)))
Expand Down Expand Up @@ -3514,7 +3527,6 @@ def Request_4_272(self, sessionid, imsi, CC_Request_Type, input_octets, output_o
response = self.generate_diameter_packet("01", "c0", 272, 4, self.generate_id(4), self.generate_id(4), avp) #Generate Diameter packet
return response


#3GPP Sh - Profile Update Request
def Request_16777217_307(self, msisdn):
avp = ''
Expand All @@ -3530,18 +3542,17 @@ def Request_16777217_307(self, msisdn):
avp += self.generate_avp(283, 40, self.OriginRealm) #Destination Realm
avp += self.generate_avp(296, 40, self.OriginRealm) #Origin Realm

self.logTool.log(service='HSS', level='debug', message="Getting susbcriber IMS info based on MSISDN", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber IMS info based on MSISDN", redisClient=self.redisMessaging)
subscriber_ims_details = self.database.Get_IMS_Subscriber(msisdn=msisdn)
self.logTool.log(service='HSS', level='debug', message="Got subscriber IMS details: " + str(subscriber_ims_details), redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting susbcriber info based on MSISDN", redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Getting subscriber info based on MSISDN", redisClient=self.redisMessaging)
subscriber_details = self.database.Get_Subscriber(msisdn=msisdn)
self.logTool.log(service='HSS', level='debug', message="Got subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)
subscriber_details = {**subscriber_details, **subscriber_ims_details}
self.logTool.log(service='HSS', level='debug', message="Merged subscriber details: " + str(subscriber_details), redisClient=self.redisMessaging)

avp += self.generate_avp(1, 40, str(binascii.hexlify(str.encode(subscriber_details['imsi'])),'ascii')) #Username AVP


#Sh-User-Data (XML)
#This loads a Jinja XML template containing the Sh-User-Data
templateLoader = jinja2.FileSystemLoader(searchpath="./")
Expand Down
7 changes: 6 additions & 1 deletion services/apiService.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,13 @@
databaseClient.Generate_JSON_Model_for_Flask(SUBSCRIBER_ROUTING)
)


#Legacy support for sh_profile. sh_profile is deprecated as of v1.0.1.
imsSubscriberModel = databaseClient.Generate_JSON_Model_for_Flask(TFT)
imsSubscriberModel['sh_profile'] = fields.String(required=False, description=IMS_SUBSCRIBER.sh_profile.doc),

IMS_SUBSCRIBER_model = api.schema_model('IMS_SUBSCRIBER JSON',
databaseClient.Generate_JSON_Model_for_Flask(IMS_SUBSCRIBER)
databaseClient.Generate_JSON_Model_for_Flask(TFT)
)

TFT_model = api.schema_model('TFT JSON',
Expand Down
Loading

0 comments on commit b5fd292

Please sign in to comment.