private IRadiusPacket Authenticate(IRadiusPacket packet)
        {
            var msisdn = packet.GetAttribute <String>("Calling-Station-Id");

            if (!packet.Attributes.ContainsKey("3GPP-User-Location-Info"))
            {
                _log.Warn("Missing 3GPP-User-Location-Info in packet, ignoring");
                return(null);
            }
            var locationInfo = Utils.GetMccMncFrom3GPPLocationInfo(packet.GetAttribute <Byte[]>("3GPP-User-Location-Info"));

            _log.Debug($"Handling authentication packet for {msisdn} on network {locationInfo.locationType}:{locationInfo.mccmnc}");
            using (var db = _contextFactory.GetContext())
            {
                if (locationInfo.mccmnc == "99999")
                {
                    _log.Warn($"No location info for msisdn {msisdn} check m2m portal 3GPP-SGSN-Address: {packet.GetAttribute<IPAddress>("3GPP-SGSN-Address")}");
                    return(packet.CreateResponsePacket(PacketCode.AccessReject));
                }
                var result = db.Authenticate1(msisdn, "flexinets", msisdn, locationInfo.mccmnc).ToList();
                if (result.Count > 0 && result.First() == null)
                {
                    var response = packet.CreateResponsePacket(PacketCode.AccessAccept);
                    response.AddAttribute("Acct-Interim-Interval", 60);
                    return(response);
                }
                else
                {
                    try
                    {
                        var mccmnc  = Convert.ToInt32(locationInfo.mccmnc);
                        var network = db.Networks.SingleOrDefault(o => o.mccmnc == mccmnc);
                        var simcard = db.SimCards.SingleOrDefault(o => o.Msisdn == msisdn);

                        var sb = new StringBuilder();

                        sb.AppendLine($"Authentication failed for {msisdn} on network {mccmnc} ({network?.providername}, {network?.countryname})");
                        if (simcard.user_id == null)
                        {
                            sb.AppendLine("Sim card not mapped to a user");
                        }
                        else
                        {
                            sb.AppendLine($"User: {simcard.UserSetting.user.username}@{simcard.UserSetting.user.realm}, group: {simcard.UserSetting.user.directory.name}");
                        }
                        _log.Warn(sb.ToString().Trim()); // todo needs throttling to reduce unwanted spam
                    }
                    catch (Exception ex)
                    {
                        _log.Error("huh?", ex);
                    }

                    return(packet.CreateResponsePacket(PacketCode.AccessReject));
                }
            }
        }
        public void PingRadiusServer(object state)
        {
            try
            {
                using (var db = _contextFactory.GetContext())
                {
                    _ipAddresses = db.FL1Settings.SingleOrDefault(o => o.Name == "PingIpAddresses").Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                }
            }
            catch (Exception ex)
            {
                _log.Error("Unable to refresh ip list, using old values", ex);
            }

            Parallel.ForEach(_ipAddresses, ipAddress =>
            {
                try
                {
                    var reply   = SendPing(ipAddress, 5000, 1);
                    var message = $"Ping from {Environment.MachineName} to {ipAddress} response {reply?.Status} in {reply?.RoundtripTime}ms";
                    _log.Debug(message);
                    using (var db = _contextFactory.GetContext())
                    {
                        db.ServerMonitorLogs.Add(new ServerMonitorLog
                        {
                            EventId        = 1,
                            EventTimestamp = DateTime.UtcNow,
                            MachineName    = Environment.MachineName,
                            Message        = message,
                            Status         = reply.Status.ToString(),
                            Target         = ipAddress
                        });
                        db.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    _log.Error("Something went wrong with ping", ex);
                }
            });
        }
Exemple #3
0
        /// <summary>
        /// Proxy iPass authentication to an external server
        /// </summary>
        /// <param name="rawusername"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public PacketCode?ProxyAuthentication(String rawusername, String password)
        {
            using (var db = _contextFactory.GetContext())
            {
                var usernamedomain = UsernameDomain.Parse(rawusername, true);
                var server         = db.Roamservers.FirstOrDefault(o => o.domain == usernamedomain.Domain);
                if (server != null)
                {
                    _log.Debug($"Found proxy server {server.host} for username {rawusername}");

                    if (!String.IsNullOrEmpty(server.rewritedomain))
                    {
                        usernamedomain.Domain = server.rewritedomain;
                        _log.Debug($"Rewriting username from {rawusername} to {usernamedomain}");
                        rawusername = usernamedomain.FullUsername;
                    }

                    ProcessStartInfo startinfo;
                    if (server.uselegacy)
                    {
                        startinfo = ProxyAuthenticationSsl(rawusername, password, server.host);
                    }
                    else
                    {
                        startinfo = ProxyAuthenticationNew(rawusername, password, server.host);
                    }

                    using (var process = new Process
                    {
                        StartInfo = startinfo
                    })
                    {
                        var sb = new StringBuilder();
                        process.OutputDataReceived += (sender, args) => sb.AppendLine(args.Data);
                        process.Start();
                        process.BeginOutputReadLine();
                        process.StandardInput.WriteLine();  // Exits the script
                        process.WaitForExit();
                        var content = sb.ToString();

                        _log.Debug(content);

                        if (content.Contains("Status: accept"))
                        {
                            return(PacketCode.AccessAccept);
                        }
                        if (content.Contains("LDAP User found but memberOf validation failed"))
                        {
                            _log.Warn($"MemberOf failed for user {rawusername}");
                        }
                        if (content.Contains("Message: LDAP search found no entries for this user"))
                        {
                            _log.Warn($"Username {rawusername} not found");
                        }
                        if (content.Contains("Status: reject"))
                        {
                            _log.Warn($"Got reject for user {rawusername} from proxy");
                        }

                        if (!(content.Contains("reject") || content.Contains("accept")))
                        {
                            _log.Error($"Invalid proxy response: {content}");
                            throw new InvalidOperationException("Something went wrong with proxy");
                        }
                    }

                    return(PacketCode.AccessReject);
                }
            }

            return(null);
        }
Exemple #4
0
        /// <summary>
        /// Accounting
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        private IRadiusPacket HandleAccountingPacket(IRadiusPacket packet)
        {
            var acctStatusType = packet.GetAttribute <AcctStatusType>("Acct-Status-Type");

            if (acctStatusType == AcctStatusType.Start || acctStatusType == AcctStatusType.Stop)
            {
                var usernamedomain = UsernameDomain.Parse(packet.GetAttribute <String>("User-Name"));
                var nodeid         = GetUserNodeId(usernamedomain.Username, usernamedomain.Domain);
                _log.Info($"Handling {acctStatusType} packet for {usernamedomain}");
                try
                {
                    using (var db = _contextFactory.GetContext())
                    {
                        var entry = new radiatoraccounting
                        {
                            username          = usernamedomain.Username,
                            realm             = usernamedomain.Domain,
                            node_id           = nodeid,
                            ACCTSTATUSTYPE    = (packet.GetAttribute <AcctStatusType>("Acct-Status-Type")).ToString(),
                            ACCTINPUTOCTETS   = Convert.ToUInt32(packet.GetAttribute <UInt32?>("Acct-Input-Octets")),
                            ACCTOUTPUTOCTETS  = Convert.ToUInt32(packet.GetAttribute <UInt32?>("Acct-Output-Octets")),
                            ACCTSESSIONID     = packet.GetAttribute <String>("Acct-Session-Id"),
                            ACCTSESSIONTIME   = Convert.ToInt32(packet.GetAttribute <UInt32?>("Acct-Session-Time")),
                            NASIDENTIFIER     = packet.GetAttribute <String>("NAS-Identifier"),
                            NASPORT           = packet.GetAttribute <UInt32?>("NAS-Port"),
                            NASPORTTYPE       = packet.GetAttribute <UInt32?>("NAS-Port-Type").ToString(),
                            WISPrLocationName = packet.GetAttribute <String>("WISPr-Location-Name"),
                            temp = packet.GetAttribute <String>("Ipass-Location-Description"),
                            timestamp_datetime = packet.Attributes.ContainsKey("Timestamp") ? (DateTime?)DateTimeOffset.FromUnixTimeSeconds(packet.GetAttribute <Int32>("Timestamp")).UtcDateTime : DateTime.UtcNow
                        };
                        db.radiatoraccountings.Add(entry);
                        db.SaveChanges();
                    }
                }
                catch (DbUpdateConcurrencyException)
                {
                    _log.Info($"Duplicate {acctStatusType} request received");
                }
                catch (Exception ex)
                {
                    _log.Error("Something went wrong", ex);
                }

                if (acctStatusType == AcctStatusType.Start)
                {
                    try
                    {
                        using (var db = _contextFactory.GetContext())
                        {
                            db.radiatoronlines.Add(new radiatoronline
                            {
                                username           = usernamedomain.Username,
                                realm              = usernamedomain.Domain,
                                node_id            = nodeid,
                                ACCTSESSIONID      = packet.GetAttribute <String>("Acct-Session-Id"),
                                timestamp_datetime = packet.Attributes.ContainsKey("Timestamp") ? (DateTime?)DateTimeOffset.FromUnixTimeSeconds(packet.GetAttribute <Int32>("Timestamp")).UtcDateTime : DateTime.UtcNow,
                                NASIDENTIFIER      = packet.GetAttribute <String>("NAS-Identifier"),
                                NASPORT            = packet.GetAttribute <UInt32?>("NAS-Port"),
                                NASPORTTYPE        = packet.GetAttribute <UInt32?>("NAS-Port-Type").ToString(),
                                WISPrLocationName  = packet.GetAttribute <String>("Ipass-Location-Description")
                            });
                            db.SaveChanges();
                        }
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        _log.Info("Cannot insert duplicate in radiatoronline");
                    }
                }
                if (acctStatusType == AcctStatusType.Stop)
                {
                    try
                    {
                        using (var db = _contextFactory.GetContext())
                        {
                            var acctsessionid = packet.GetAttribute <String>("Acct-Session-Id");
                            var online        = db.radiatoronlines.SingleOrDefault(o => o.ACCTSESSIONID == acctsessionid);
                            if (online != null)
                            {
                                db.radiatoronlines.Remove(online);
                                db.SaveChanges();
                            }
                        }
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        _log.Info("Nothing to remove from online");
                    }
                }
            }
            return(packet.CreateResponsePacket(PacketCode.AccountingResponse));
        }
Exemple #5
0
        public async Task LoadSessionsAsync(DateTime fromdate, DateTime todate)
        {
            _log.Info($"Loading sessions from {fromdate} to {todate}");

            using (var db = _contextFactory.GetContext())
            {
                var customers = await GetAccountsAsync();

                using (var client = await CreateAuthenticatedHttpClientAsync())
                {
                    client.Timeout = TimeSpan.FromMinutes(2);
                    foreach (var customer in customers)
                    {
                        try
                        {
                            var url = $"https://openmobile.ipass.com/moservices/rest/api/ipass/{customer.customerId}/mo/reports/central-csv?report=connectionActivity&startdate={fromdate:MM-dd-yyyy}&enddate={todate:MM-dd-yyyy}&sess-type=initiated&pageSize=0";
                            using (var contentstream = await client.GetStreamAsync(url))
                            {
                                using (var connection = _contextFactory.GetSqlConnection())
                                {
                                    var reader  = new StreamReader(contentstream);
                                    var content = await reader.ReadToEndAsync();

                                    content = content.Replace("\"", "");
                                    var stream    = new MemoryStream(Encoding.UTF8.GetBytes(content));
                                    var csvreader = new CsvReader(new StreamReader(stream), true, ',');
                                    var bulkcopy  = new SqlBulkCopy(connection)
                                    {
                                        DestinationTableName = "Insight.SessionsV2",
                                        BulkCopyTimeout      = 60,
                                        BatchSize            = 10000
                                    };
                                    bulkcopy.ColumnMappings.Add(0, "AccountId");
                                    bulkcopy.ColumnMappings.Add(1, "[UsernameDomain]");
                                    bulkcopy.ColumnMappings.Add(3, "[ProfileId]");
                                    bulkcopy.ColumnMappings.Add(4, "[SessionId]");
                                    bulkcopy.ColumnMappings.Add(5, "[StartTime]");
                                    bulkcopy.ColumnMappings.Add(6, "[SessionLength]");
                                    bulkcopy.ColumnMappings.Add(7, "[AuthenticationTime]");
                                    bulkcopy.ColumnMappings.Add(8, "[ConnectionType]");
                                    bulkcopy.ColumnMappings.Add(9, "[ConnectionStatus]");
                                    bulkcopy.ColumnMappings.Add(10, "[ConnectionStatusCode]");
                                    bulkcopy.ColumnMappings.Add(11, "[ConnectionStatusCodeType]");
                                    bulkcopy.ColumnMappings.Add(12, "[ConnectionStatusCodeDescription]");
                                    bulkcopy.ColumnMappings.Add(13, "[DisconnectCode]");
                                    bulkcopy.ColumnMappings.Add(14, "[ClientIpAddress]");
                                    bulkcopy.ColumnMappings.Add(15, "[DownloadedMB]");
                                    bulkcopy.ColumnMappings.Add(17, "[UploadedMB]");
                                    bulkcopy.ColumnMappings.Add(18, "[SignalStrength]");
                                    bulkcopy.ColumnMappings.Add(19, "[Country]");
                                    bulkcopy.ColumnMappings.Add(20, "[ClientMacAddress]");
                                    bulkcopy.ColumnMappings.Add(21, "[Ssid]");
                                    bulkcopy.ColumnMappings.Add(22, "[AuthMethod]");
                                    bulkcopy.ColumnMappings.Add(23, "[SecurityMode]");
                                    bulkcopy.ColumnMappings.Add(24, "[DeviceType]");
                                    bulkcopy.ColumnMappings.Add(25, "[DeviceOS]");
                                    bulkcopy.ColumnMappings.Add(26, "[ClientVersion]");
                                    bulkcopy.ColumnMappings.Add(27, "[SdkVersion]");
                                    bulkcopy.ColumnMappings.Add(28, "[ConnectReason]");

                                    connection.Open();

                                    // Veeeewwy veeewwy important! Otherwise decimal parsing from eg 5.53 will fail
                                    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
                                    await bulkcopy.WriteToServerAsync(csvreader);

                                    _log.Info($"Imported sessions for {customer.name}");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            _log.Error($"{customer.name} failed to download: ", ex);
                        }
                    }
                }

                _log.Info("Updating nodeids");
                var update = @"
BEGIN TRANSACTION
UPDATE Insight.SessionsV2
SET node_id = users.node_id
FROM Insight.SessionsV2 AS i LEFT JOIN users ON CONCAT(users.username, '@', users.realm) = i.UsernameDomain
WHERE CONCAT(users.username, '@', users.realm) = i.UsernameDomain AND i.node_id IS NULL

UPDATE Insight.SessionsV2
SET node_id = (SELECT TOP 1 t1.node_id
                FROM ipass_realms AS t1
                LEFT JOIN directory ON(t1.node_id = directory.node_id)
                WHERE realm = SUBSTRING(UsernameDomain, LEN(usernamedomain) - CHARINDEX('@', REVERSE(UsernameDomain)) + 2, LEN(UsernameDomain))
                ORDER BY directory.lft)
FROM Insight.SessionsV2 AS i
WHERE i.node_id IS NULL

UPDATE Insight.SessionsV2
SET node_id = (SELECT TOP 1 node_id
                FROM directory
                WHERE ipassCustomerID = AccountId
                ORDER BY directory.lft)
FROM Insight.SessionsV2 AS i
WHERE i.node_id IS NULL

COMMIT";
                await db.Database.ExecuteSqlCommandAsync(update);


                _log.Info("Updating summary tables");
                var updatesummary = @"
DELETE FROM ipass.CombinedCdrUsers WHERE Month >= @fromdate
INSERT INTO ipass.CombinedCdrUsers (Month, UsernameDomain, NodeId, GiSessions, DsSessions, Sum, Seconds)

SELECT 
	monthdatetime,
	UsernameDomain,
	node_id,
	SUM(CASE WHEN c.type = 'gi' THEN 1 ELSE 0 END) AS gisessions,
	SUM(CASE WHEN c.type = 'ds' THEN 1 ELSE 0 END) AS dssessions,
	SUM(sum) AS sum,
	SUM(duration) AS seconds

FROM ipass.CdrCombined AS c
WHERE node_id IS NOT NULL AND UsernameDomain IS NOT NULL AND monthdatetime >= @fromdate
GROUP BY monthdatetime, UsernameDomain,node_id

DELETE FROM ipass.combinedcdrgroups WHERE month >= @fromdate
INSERT INTO iPass.CombinedCdrGroups (Month, NodeId, Seconds, Sum, BothUsers, GiUsers, DsUsers, DsSessions, GiSession)

SELECT 
	u.Month,
	u.NodeId,
	SUM(u.Seconds),
	SUM(u.Sum),
	SUM(CASE WHEN u.DsSessions > 0 AND u.GiSessions > 0 THEN 1 ELSE 0 END) AS bothuser,
	SUM(CASE WHEN u.DsSessions = 0 AND u.GiSessions > 0 THEN 1 ELSE 0 END) AS giuser,
	SUM(CASE WHEN u.DsSessions > 0 AND u.GiSessions = 0 THEN 1 ELSE 0 END) AS dsuser,
	SUM(u.DsSessions),
	SUM(u.GiSessions)
	
FROM iPass.CombinedCdrUsers AS u
WHERE Month >= @fromdate
GROUP BY u.Month, u.NodeId";

                var summaryfromdate = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.AddMonths(-1).Month, 1);
                await db.Database.ExecuteSqlCommandAsync(updatesummary, new SqlParameter("@fromdate", summaryfromdate));
            }
            _log.Info("Import done");
        }
        public void CheckWelcomeSms(String msisdn)
        {
            _log.Debug($"Checking welcome sms for msisdn {msisdn}");
            using (var db = _contextFactory.GetContext())
            {
                var currentsession = (from o in db.Onlines
                                      where o.Calling_Station_Id == msisdn
                                      select o).SingleOrDefault();

                if (currentsession == null)
                {
                    _log.Error($"Couldnt find current session for msisdn: {msisdn}");
                    return;
                }
                if (!currentsession.NetworkId.HasValue || currentsession.NetworkId.Value == 0)
                {
                    _log.Error($"Invalid networkid found for msisdn: {msisdn}");
                    return;
                }

                var simcard = (from o in db.SimCards
                               where o.Msisdn == msisdn
                               select o).SingleOrDefault();

                if (simcard == null)
                {
                    _log.Warn($"Couldnt find sim card with msisdn: {msisdn}");
                    return;
                }
                if (simcard.UserSetting == null)
                {
                    _log.Warn($"Sim card {simcard.Msisdn} not mapped to a user?!");
                    return;
                }

                _log.Debug($"Found sim card with msisdn: {simcard.Msisdn}");


                var network = (from o in db.PricesViews
                               where o.mccmnc == currentsession.NetworkId && o.PricelistId == simcard.UserSetting.user.directory.GroupSetting.PricelistId
                               select o).SingleOrDefault();

                if (network == null)
                {
                    _log.Error($"NetworkId {currentsession.NetworkId} not found?! Wtf?");
                    return;
                }

                // Check if there has been a session on the same network within a week
                var lastsession = (from o in db.Accountings
                                   orderby o.Event_Timestamp descending
                                   where o.Calling_Station_Id == simcard.Msisdn && o.Acct_Status_Type == "stop"
                                   select o).FirstOrDefault();

                if (lastsession == null)
                {
                    // Dont send an sms on the first connection, allow setup
                    _log.Debug($"Sim card {simcard.Msisdn}, previous NetworkId: n/a, current NetworkId: {currentsession.NetworkId}");
                    //SendWelcomeSms(simcard.UserSetting.user, network);
                }
                else if (lastsession.Event_Timestamp < DateTime.UtcNow.AddDays(-7))     // Over a week since the last session
                {
                    _log.Debug($"Sim card {simcard.Msisdn}, over 1 week since last connection, current NetworkId: {currentsession.NetworkId}");
                    SendWelcomeSms(simcard.UserSetting.user, network);
                }
                else if (lastsession.NetworkId.HasValue && lastsession.NetworkId.Value != currentsession.NetworkId)
                {
                    _log.Debug($"Sim card {simcard.Msisdn}, previous NetworkId: {lastsession.NetworkId}, current NetworkId: {currentsession.NetworkId}");
                    SendWelcomeSms(simcard.UserSetting.user, network);
                }
                else
                {
                    _log.Debug($"Sim card {simcard.Msisdn} on same network");
                }
            }
        }