Beispiel #1
0
        public static YubicoResponse Validate(List <string> urls, string userAgent)
        {
            List <Task <YubicoResponse> > tasks        = new List <Task <YubicoResponse> >();
            CancellationTokenSource       cancellation = new CancellationTokenSource();

            foreach (string url in urls)
            {
                Task <YubicoResponse> task = new Task <YubicoResponse>((o) =>
                {
                    return(Verify((string)o, userAgent));
                }, url, cancellation.Token);

                tasks.Add(task);
                task.Start();
            }

            YubicoResponse     response      = null;
            AggregateException taskException = null;

            while (tasks.Count != 0)
            {
                int completed = Task.WaitAny(tasks.ToArray());
                Task <YubicoResponse> task = tasks[completed];
                tasks.Remove(task);

                try
                {
                    if (task.Result != null)
                    {
                        if (response == null || (task.Result.GetStatus() == YubicoResponseStatus.OK))
                        {
                            response = task.Result;
                        }

                        cancellation.Cancel();
                    }
                }
                catch (AggregateException ex)
                {
                    taskException = ex;
                }
            }

            if (response == null && taskException != null)
            {
                throw taskException.Flatten();
            }

            return(response);
        }
Beispiel #2
0
        protected override bool ValidateUserNameCredential(string userName, string password, out List <Claim> claims)
        {
            claims = new List <Claim>();

            int otpLength = 32 + _config.YubicoSettings.PublicIdLength;

            if (password.Length >= otpLength)
            {
                string otp = password.Substring(password.Length - otpLength, otpLength);

                if (YubicoClient.IsOtpValidFormat(otp))
                {
                    string windowsPassword = password.Substring(0, password.Length - otpLength);

                    List <Claim> windowsClaims;

                    if (base.ValidateUserNameCredential(userName, windowsPassword, out windowsClaims))
                    {
                        using (PrincipalContext context = GetContext(userName, windowsPassword))
                        {
                            using (Principal principal = Principal.FindByIdentity(context, userName))
                            {
                                using (DirectoryEntry directoryEntry = principal.GetUnderlyingObject() as DirectoryEntry)
                                {
                                    string publicId = null;

                                    if (directoryEntry.Properties.Contains(_config.YubicoSettings.PublicIdAttributeName))
                                    {
                                        publicId = directoryEntry.Properties[_config.YubicoSettings.PublicIdAttributeName].Value.ToString();
                                    }

                                    if (!string.IsNullOrEmpty(publicId))
                                    {
                                        YubicoClient client = new YubicoClient(_config.YubicoSettings.ClientId, _config.YubicoSettings.APIKey);
                                        client.SetUrls(_apiUrls);

                                        YubicoResponse response = client.Validate(otp);

                                        if (response != null)
                                        {
                                            if (response.GetStatus() == YubicoResponseStatus.OK && response.GetPublicId() == publicId)
                                            {
                                                claims.AddRange(windowsClaims);
                                                return(true);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        LogEntry entry = new LogEntry();
                                        entry.Severity = TraceEventType.Error;
                                        entry.Priority = -1;

                                        if (Logger.ShouldLog(entry))
                                        {
                                            entry.Message = string.Format("Unable to find the user's PublicId. PublicIdAttributeName=\"{0}\".", _config.YubicoSettings.PublicIdAttributeName);
                                            Logger.Write(entry);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    LogEntry entry = new LogEntry();
                    entry.Severity = TraceEventType.Error;
                    entry.Priority = -1;

                    if (Logger.ShouldLog(entry))
                    {
                        entry.Message = "Invalid OTP Format.";
                        Logger.Write(entry);
                    }
                }
            }
            else
            {
                LogEntry entry = new LogEntry();
                entry.Severity = TraceEventType.Error;
                entry.Priority = -1;

                if (Logger.ShouldLog(entry))
                {
                    entry.Message = "Invalid OTP Length.";
                    Logger.Write(entry);
                }
            }

            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// Do verification of OTP
        /// </summary>
        /// <param name="otp">The OTP from a YubiKey in modhex</param>
        /// <returns>YubicoResponse indicating status of the request</returns>
        /// <exception cref="YubicoValidationFailure"/>
        /// <exception cref="FormatException"/>
        public YubicoResponse Validate(string otp)
        {
            if (!IsOtpValidFormat(otp))
            {
                throw new YubicoValidationException("Bad OTP format.");
            }

            if (_nonce == null)
            {
                _nonce = GenerateNonce();
            }

            SortedDictionary <string, string> queryMap = new SortedDictionary <string, string>();

            queryMap.Add("id", _clientId);
            queryMap.Add("nonce", _nonce);
            queryMap.Add("otp", otp);
            queryMap.Add("timestamp", "1");

            if (_sync != null)
            {
                queryMap.Add("sl", _sync);
            }

            string query = null;

            foreach (KeyValuePair <string, string> pair in queryMap)
            {
                if (query == null)
                {
                    query = "";
                }
                else
                {
                    query += "&";
                }
                query += pair.Key + "=" + Uri.EscapeDataString(pair.Value);
            }

            if (_apiKey != null)
            {
                query += "&h=" + Uri.EscapeDataString(DoSignature(query, _apiKey));
            }

            List <string> urls = new List <string>();

            foreach (string url in _apiUrls)
            {
                urls.Add(url + "?" + query);
            }

            try
            {
                YubicoResponse response = YubicoValidate.Validate(urls, _userAgent);

                if (_apiKey != null && response.GetStatus() != YubicoResponseStatus.BAD_SIGNATURE)
                {
                    string responseString  = null;
                    string serverSignature = null;

                    foreach (KeyValuePair <string, string> pair in response.GetResponseMap())
                    {
                        if (pair.Key.Equals("h"))
                        {
                            serverSignature = pair.Value;
                        }
                        else
                        {
                            if (responseString == null)
                            {
                                responseString = "";
                            }
                            else
                            {
                                responseString += "&";
                            }

                            responseString += pair.Key + "=" + pair.Value;
                        }
                    }

                    string clientSignature = DoSignature(responseString, _apiKey);

                    if (serverSignature == null || !clientSignature.Equals(serverSignature))
                    {
                        throw new YubicoValidationException("Server signature did not match the key.");
                    }
                }

                if (response.GetStatus() == YubicoResponseStatus.OK)
                {
                    if (!response.GetNonce().Equals(_nonce))
                    {
                        throw new YubicoValidationException("Nonce in request and response does not match.");
                    }
                    else if (!response.GetOtp().Equals(otp))
                    {
                        throw new YubicoValidationException("OTP in request and response does not match.");
                    }

                    return(response);
                }

                throw new YubicoValidationException(string.Format("OTP validation failed: {0}", response.GetStatus()));
            }
            finally
            {
                // set nonce to null so we will generate a new one for the next request
                _nonce = null;
            }
        }