Beispiel #1
0
            public override string GetString(int column)
            {
                try
                {
                    if ((Position >= _entriesWithContexts.Count) || (Position < 0))
                    {
                        return("");
                    }

                    switch (column)
                    {
                    case 0:     // _ID
                        return(Position.ToString(CultureInfo.InvariantCulture));

                    case 1:     // SuggestColumnText1
                        return(CurrentEntry.Strings.ReadSafe(PwDefs.TitleField));

                    case 2:     // SuggestColumnText2
                        return(Internationalise(_entriesWithContexts[Position].resultContext));

                    case 3:     // SuggestColumnIcon1
                        var builder = new Android.Net.Uri.Builder();
                        builder.Scheme(ContentResolver.SchemeContent);
                        builder.Authority(Authority);
                        builder.Path(GetIconPathQuery);
                        builder.AppendQueryParameter(IconIdParameter, CurrentEntry.IconId.ToString());
                        builder.AppendQueryParameter(CustomIconUuidParameter, CurrentEntry.CustomIconUuid.ToHexString());
                        builder.AppendQueryParameter(DatabaseIndexParameter, _entriesWithContexts[Position].DatabaseIndex.ToString());
                        return(builder.Build().ToString());

                    case 4:     // SuggestColumnIntentDataId
                        return(new ElementAndDatabaseId(App.Kp2a.FindDatabaseForElement(CurrentEntry), CurrentEntry).FullId);

                    default:
                        return(null);
                    }
                }
                catch (Exception e)
                {
                    Kp2aLog.LogUnexpectedError(e);
                    return("(error retrieving data)");
                }
            }
Beispiel #2
0
        private DateTime ReadTime(XmlReader xr)
        {
            // Cf. WriteObject(string, DateTime)
            if ((m_format == KdbxFormat.Default) && (m_uFileVersion >= FileVersion32_4))
            {
                // long l = ReadLong(xr, -1);
                // if(l != -1) return DateTime.FromBinary(l);

                string str = ReadString(xr);
                byte[] pb  = Convert.FromBase64String(str);
                if (pb.Length != 8)
                {
                    Debug.Assert(false);
                    byte[] pb8 = new byte[8];
                    Array.Copy(pb, pb8, Math.Min(pb.Length, 8));                     // Little-endian
                    pb = pb8;
                }
                long lSec = MemUtil.BytesToInt64(pb);
                try
                {
                    return(new DateTime(lSec * TimeSpan.TicksPerSecond, DateTimeKind.Utc));
                }
                catch (System.ArgumentOutOfRangeException e)
                {
                    //files might contain bad data, e.g. see #868. Fall back to MinValue
                    Kp2aLog.Log("Failed to read date from file.");
                    return(DateTime.MinValue);
                }
            }
            else
            {
                string str = ReadString(xr);

                DateTime dt;
                if (TimeUtil.TryDeserializeUtc(str, out dt))
                {
                    return(dt);
                }
            }

            Debug.Assert(false);
            return(m_dtNow);
        }
        private void Query(SearchParameters searchParams)
        {
            try {
                Group = App.Kp2a.GetDb().Search(searchParams, null);
            } catch (Exception e) {
                Kp2aLog.LogUnexpectedError(e);
                Toast.MakeText(this, e.Message, ToastLength.Long).Show();
                Finish();
                return;
            }

            if (Group == null || (!Group.Entries.Any()))
            {
                SetContentView(Resource.Layout.group_empty);
            }

            SetGroupTitle();

            FragmentManager.FindFragmentById <GroupListFragment>(Resource.Id.list_fragment).ListAdapter = new PwGroupListAdapter(this, Group);
        }
 public static bool TryTakePersistablePermissions(ContentResolver contentResolver, Android.Net.Uri uri)
 {
     if ((int)Build.VERSION.SdkInt >= 19)
     {
         //try to take persistable permissions
         try
         {
             Kp2aLog.Log("TakePersistableUriPermission");
             var takeFlags = (ActivityFlags.GrantReadUriPermission
                              | ActivityFlags.GrantWriteUriPermission);
             contentResolver.TakePersistableUriPermission(uri, takeFlags);
             return(true);
         }
         catch (Exception e)
         {
             Kp2aLog.Log(e.ToString());
         }
     }
     return(false);
 }
        public static Uri IocToUri(IOConnectionInfo ioc)
        {
            if (!string.IsNullOrEmpty(ioc.UserName))
            {
                //legacy support.
                return(new Uri(ioc.Path));
            }
            string path = ioc.Path;
            //remove additional stuff like TLS param
            int    schemeLength = path.IndexOf("://", StringComparison.Ordinal);
            string scheme       = path.Substring(0, schemeLength);

            path = path.Substring(schemeLength + 3);
            if (path.StartsWith(ConnectionSettings.SettingsPrefix))
            {
                //this should always be the case. However, in rare cases we might get an ioc with legacy path but no username set (if they only want to get a display name)
                string settings = path.Substring(0, path.IndexOf(ConnectionSettings.SettingsPostFix, StringComparison.Ordinal));
                path = path.Substring(settings.Length + 1);
            }
            Kp2aLog.Log("FTP: IocToUri out = " + scheme + "://" + path);
            return(new Uri(scheme + "://" + path));
        }
Beispiel #6
0
 protected override void OnPreExecute()
 {
     new Handler().PostDelayed(() =>
     {
         if (!mFinished)
         {
             try
             {
                 /*
                  * sometime the activity has been finished before we
                  * show this dialog, it will raise error
                  */
                 mDialog.Show();
             }
             catch (Exception t)
             {
                 Kp2aLog.LogUnexpectedError(t);
             }
         }
     }
                               , mDelayTime);
 }
        /// <summary>
        /// Wraps autofill data in a LoginCredential  Dataset object which can then be sent back to the
        /// client View.
        /// </summary>
        /// <returns>The dataset.</returns>
        /// <param name="context">Context.</param>
        /// <param name="autofillFields">Autofill fields.</param>
        /// <param name="filledAutofillFieldCollection">Filled autofill field collection.</param>
        public static Dataset NewDataset(Context context,
                                         AutofillFieldMetadataCollection autofillFields, FilledAutofillFieldCollection filledAutofillFieldCollection, IAutofillIntentBuilder intentBuilder)
        {
            var datasetName = filledAutofillFieldCollection.DatasetName ?? "[noname]";

            var datasetBuilder = new Dataset.Builder(NewRemoteViews(context.PackageName, datasetName, intentBuilder.AppIconResource));

            datasetBuilder.SetId(datasetName);

            var setValueAtLeastOnce = filledAutofillFieldCollection.ApplyToFields(autofillFields, datasetBuilder);


            if (setValueAtLeastOnce)
            {
                return(datasetBuilder.Build());
            }
            else
            {
                Kp2aLog.Log("Failed to set at least one value. #fields=" + autofillFields.GetAutofillIds().Length + " " + autofillFields.FocusedAutofillCanonicalHints);
            }

            return(null);
        }
        public bool IsReadOnly(IOConnectionInfo ioc, OptionalOut <UiStringKey> reason = null)
        {
            ICursor cursor = null;

            try
            {
                //on pre-Kitkat devices, we can't write content:// files
                if (!IsKitKatOrLater)
                {
                    Kp2aLog.Log("File is read-only because we're not on KitKat or later.");
                    if (reason != null)
                    {
                        reason.Result = UiStringKey.ReadOnlyReason_PreKitKat;
                    }
                    return(true);
                }

                //in previous implementations, we were checking for FLAG_SUPPORTS_WRITE in the document flags,
                //but it seems like this is very poorly supported, e.g. Dropbox and OneDrive return !FLAG_SUPPORTS_WRITE
                //even though writing work.
                return(false);
            }
            catch (Exception e)
            {
                Kp2aLog.LogUnexpectedError(e);
                //better return false here. We don't really know what happened (as this is unexpected).
                //let the user try to write the file. If it fails they will get an exception string.
                return(false);
            }
            finally
            {
                if (cursor != null)
                {
                    cursor.Close();
                }
            }
        }
Beispiel #9
0
        public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
        {
            if (App.Kp2a.DatabaseIsUnlocked)             // Can't show suggestions if the database is locked!
            {
                switch ((UriMatches)UriMatcher.Match(uri))
                {
                case UriMatches.GetSuggestions:
                    var searchString = selectionArgs[0];
                    if (!String.IsNullOrEmpty(searchString))
                    {
                        try
                        {
                            var resultsContexts = new Dictionary <PwUuid, KeyValuePair <string, string> >();
                            var result          = _db.Search(new SearchParameters {
                                SearchString = searchString
                            }, resultsContexts);
                            return(new GroupCursor(result, resultsContexts));
                        }
                        catch (Exception e)
                        {
                            Kp2aLog.LogUnexpectedError(new Exception("Failed to search for suggestions", e));
                        }
                    }
                    break;

                case UriMatches.GetIcon:
                    return(null);                            // This will be handled by OpenAssetFile

                default:
                    return(null);
                    //throw new ArgumentException("Unknown Uri: " + uri, "uri");
                }
            }

            return(null);
        }
Beispiel #10
0
        public static byte[] ReadFile(IOConnectionInfo ioc)
        {
            Stream       sIn = null;
            MemoryStream ms  = null;

            try
            {
                sIn = IOConnection.OpenRead(ioc);
                if (sIn == null)
                {
                    return(null);
                }

                ms = new MemoryStream();
                MemUtil.CopyStream(sIn, ms);

                return(ms.ToArray());
            }
            catch (Exception e)
            {
                Kp2aLog.Log("error opening file: " + e);
            }
            finally
            {
                if (sIn != null)
                {
                    sIn.Close();
                }
                if (ms != null)
                {
                    ms.Close();
                }
            }

            return(null);
        }
        private static byte[] GetOtpSecret(IDictionary <string, string> entryFields, string strPrefix)
        {
            try
            {
                string str;
                entryFields.TryGetValue(strPrefix + "Secret", out str);
                if (!string.IsNullOrEmpty(str))
                {
                    return(StrUtil.Utf8.GetBytes(str));
                }

                entryFields.TryGetValue(strPrefix + "Secret-Hex", out str);
                if (!string.IsNullOrEmpty(str))
                {
                    return(MemUtil.HexStringToByteArray(str));
                }

                entryFields.TryGetValue(strPrefix + "Secret-Base32", out str);
                if (!string.IsNullOrEmpty(str))
                {
                    return(MemUtil.ParseBase32(str));
                }

                entryFields.TryGetValue(strPrefix + "Secret-Base64", out str);
                if (!string.IsNullOrEmpty(str))
                {
                    return(Convert.FromBase64String(str));
                }
            }
            catch (Exception e)
            {
                Kp2aLog.LogUnexpectedError(e);
            }

            return(null);
        }
        protected override void OnCreate(Bundle savedInstanceState)
        {
            Kp2aLog.Log("ChooseForAutofillActivityBase.OnCreate");
            base.OnCreate(savedInstanceState);

            //if launched from history, don't re-use the task. Proceed to FileSelect instead.
            if (Intent.Flags.HasFlag(ActivityFlags.LaunchedFromHistory))
            {
                Kp2aLog.Log("ChooseForAutofillActivityBase: started from history");
                Kp2aLog.Log("Forwarding to FileSelect. QueryCredentialsActivity started from history.");
                RestartApp();
                return;
            }

            string requestedUrl = Intent.GetStringExtra(ExtraQueryString);

            if (requestedUrl == null)
            {
                Kp2aLog.Log("ChooseForAutofillActivityBase: no requestedUrl ");
                Toast.MakeText(this, "Cannot execute query for null.", ToastLength.Long).Show();
                RestartApp();
                return;
            }

            if (Intent.HasExtra(ExtraDisplayWarning))
            {
                AutofillServiceBase.DisplayWarning warning =
                    (AutofillServiceBase.DisplayWarning)Intent.GetIntExtra(ExtraDisplayWarning, (int)AutofillServiceBase.DisplayWarning.None);
                Kp2aLog.Log("ChooseForAutofillActivityBase: ExtraDisplayWarning = " + warning);
                if (warning != AutofillServiceBase.DisplayWarning.None)
                {
                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.SetTitle(this.GetString(Resource.String.AutofillWarning_title));

                    string appName            = Intent.GetStringExtra(ExtraQueryPackageString);
                    string appNameWithPackage = appName;
                    try
                    {
                        var appInfo = PackageManager.GetApplicationInfo(appName, 0);
                        if (appInfo != null)
                        {
                            appName            = PackageManager.GetApplicationLabel(appInfo);
                            appNameWithPackage = appName + " (" + Intent.GetStringExtra(ExtraQueryPackageString) + ")";
                        }
                    }
                    catch (Exception)
                    {
                        // ignored
                    }

                    builder.SetMessage(
                        GetString(Resource.String.AutofillWarning_Intro, new Java.Lang.Object[]
                    {
                        Intent.GetStringExtra(ExtraQueryDomainString), appNameWithPackage
                    })
                        + " " +
                        this.GetString(Resource.String.AutofillWarning_FillDomainInUntrustedApp, new Java.Lang.Object[]
                    {
                        Intent.GetStringExtra(ExtraQueryDomainString), appName
                    }));

                    builder.SetPositiveButton(this.GetString(Resource.String.Continue),
                                              (dlgSender, dlgEvt) =>
                    {
                        new Kp2aDigitalAssetLinksDataSource(this).RememberTrustedLink(Intent.GetStringExtra(ExtraQueryDomainString),
                                                                                      Intent.GetStringExtra(ExtraQueryPackageString));
                        Proceed();
                    });
                    builder.SetNeutralButton(this.GetString(Resource.String.AutofillWarning_trustAsBrowser, new Java.Lang.Object[]
                                                            { appName }),
                                             (sender, args) =>
                    {
                        new Kp2aDigitalAssetLinksDataSource(this).RememberAsTrustedApp(Intent.GetStringExtra(ExtraQueryPackageString));
                        Proceed();
                    });

                    builder.SetNegativeButton(this.GetString(Resource.String.cancel), (dlgSender, dlgEvt) =>
                    {
                        Finish();
                    });


                    Dialog dialog = builder.Create();
                    dialog.Show();
                    return;
                }
            }
            else
            {
                Kp2aLog.Log("ChooseForAutofillActivityBase: No ExtraDisplayWarning");
            }
            Proceed();
        }
        /// <summary>
        /// Load a KDBX file from a stream.
        /// </summary>
        /// <param name="sSource">Stream to read the data from. Must contain
        /// a KDBX stream.</param>
        /// <param name="fmt">Format.</param>
        /// <param name="slLogger">Status logger (optional).</param>
        public void Load(Stream sSource, KdbxFormat fmt, IStatusLogger slLogger)
        {
            Debug.Assert(sSource != null);
            if (sSource == null)
            {
                throw new ArgumentNullException("sSource");
            }

            if (m_bUsedOnce)
            {
                throw new InvalidOperationException("Do not reuse KdbxFile objects!");
            }
            m_bUsedOnce = true;

#if KDBX_BENCHMARK
            Stopwatch swTime = Stopwatch.StartNew();
#endif

            m_format   = fmt;
            m_slLogger = slLogger;

            m_pbsBinaries.Clear();

            UTF8Encoding encNoBom    = StrUtil.Utf8;
            byte[]       pbCipherKey = null;
            byte[]       pbHmacKey64 = null;

            List <Stream> lStreams = new List <Stream>();
            lStreams.Add(sSource);

            HashingStreamEx sHashing = new HashingStreamEx(sSource, false, null);
            lStreams.Add(sHashing);

            try
            {
                Stream sXml;
                if (fmt == KdbxFormat.Default || fmt == KdbxFormat.ProtocolBuffers)
                {
                    BinaryReaderEx br = new BinaryReaderEx(sHashing,
                                                           encNoBom, KLRes.FileCorrupted);
                    byte[] pbHeader = LoadHeader(br);
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

                    int           cbEncKey, cbEncIV;
                    ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);

                    if (m_slLogger != null)
                    {
                        m_slLogger.SetText("KP2AKEY_TransformingKey", LogStatusType.AdditionalInfo);
                    }

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    string strIncomplete = KLRes.FileHeaderCorrupted + " " +
                                           KLRes.FileIncomplete;

                    Stream sPlain;
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        Stream sDecrypted = EncryptStream(sHashing, iCipher,
                                                          pbCipherKey, cbEncIV, false);
                        if ((sDecrypted == null) || (sDecrypted == sHashing))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }

                        if (m_slLogger != null)
                        {
                            m_slLogger.SetText("KP2AKEY_DecodingDatabase", LogStatusType.AdditionalInfo);
                        }

                        lStreams.Add(sDecrypted);

                        BinaryReaderEx brDecrypted = new BinaryReaderEx(sDecrypted,
                                                                        encNoBom, strIncomplete);
                        byte[] pbStoredStartBytes = brDecrypted.ReadBytes(32);

                        if ((m_pbStreamStartBytes == null) || (m_pbStreamStartBytes.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(pbStoredStartBytes, m_pbStreamStartBytes))
                        {
                            throw new InvalidCompositeKeyException();
                        }

                        if (m_slLogger != null)
                        {
                            m_slLogger.SetText("KP2AKEY_DecodingDatabase", LogStatusType.AdditionalInfo);
                        }


                        sPlain = new HashedBlockStream(sDecrypted, false, 0, !m_bRepairMode);
                    }
                    else                     // KDBX >= 4
                    {
                        byte[] pbStoredHash = MemUtil.Read(sHashing, 32);
                        if ((pbStoredHash == null) || (pbStoredHash.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(m_pbHashOfHeader, pbStoredHash))
                        {
                            throw new InvalidDataException(KLRes.FileHeaderCorrupted);
                        }

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        byte[] pbStoredHmac = MemUtil.Read(sHashing, 32);
                        if ((pbStoredHmac == null) || (pbStoredHmac.Length != 32))
                        {
                            throw new EndOfStreamException(strIncomplete);
                        }
                        if (!MemUtil.ArraysEqual(pbHeaderHmac, pbStoredHmac))
                        {
                            throw new InvalidCompositeKeyException();
                        }

                        HmacBlockStream sBlocks = new HmacBlockStream(sHashing,
                                                                      false, !m_bRepairMode, pbHmacKey64);
                        lStreams.Add(sBlocks);

                        sPlain = EncryptStream(sBlocks, iCipher, pbCipherKey,
                                               cbEncIV, false);
                        if ((sPlain == null) || (sPlain == sBlocks))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                    }
                    lStreams.Add(sPlain);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        sXml = new GZipStream(sPlain, CompressionMode.Decompress);
                        lStreams.Add(sXml);
                    }
                    else
                    {
                        sXml = sPlain;
                    }

                    if (m_uFileVersion >= FileVersion32_4)
                    {
                        LoadInnerHeader(sXml);                         // Binary header before XML
                    }
                }
                else if (fmt == KdbxFormat.PlainXml)
                {
                    sXml = sHashing;
                }
                else
                {
                    Debug.Assert(false); throw new ArgumentOutOfRangeException("fmt");
                }

                if (fmt == KdbxFormat.Default)
                {
                    if (m_pbInnerRandomStreamKey == null)
                    {
                        Debug.Assert(false);
                        throw new SecurityException("Invalid inner random stream key!");
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }
                if (m_slLogger != null)
                {
                    m_slLogger.SetText("KP2AKEY_ParsingDatabase", LogStatusType.AdditionalInfo);
                }

#if KeePassDebug_WriteXml
                // FileStream fsOut = new FileStream("Raw.xml", FileMode.Create,
                //	FileAccess.Write, FileShare.None);
                // try
                // {
                //	while(true)
                //	{
                //		int b = sXml.ReadByte();
                //		if(b == -1) break;
                //		fsOut.WriteByte((byte)b);
                //	}
                // }
                // catch(Exception) { }
                // fsOut.Close();
#endif
                var stopWatch = Stopwatch.StartNew();

                if (fmt == KdbxFormat.ProtocolBuffers)
                {
                    KdbpFile.ReadDocument(m_pwDatabase, sXml, m_pbInnerRandomStreamKey, m_pbHashOfHeader);

                    Kp2aLog.Log(String.Format("KdbpFile.ReadDocument: {0}ms", stopWatch.ElapsedMilliseconds));
                }
                else
                {
                    ReadXmlStreamed(sXml, sHashing);

                    Kp2aLog.Log(String.Format("ReadXmlStreamed: {0}ms", stopWatch.ElapsedMilliseconds));
                }
                // ReadXmlDom(sXml);
            }
            catch (CryptographicException)            // Thrown on invalid padding
            {
                throw new CryptographicException(KLRes.FileCorrupted);
            }
            finally
            {
                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }

                CommonCleanUpRead(lStreams, sHashing);
            }

#if KDBX_BENCHMARK
            swTime.Stop();
            MessageService.ShowInfo("Loading KDBX took " +
                                    swTime.ElapsedMilliseconds.ToString() + " ms.");
#endif
        }
Beispiel #14
0
        public bool IsReadOnly(IOConnectionInfo ioc, OptionalOut <UiStringKey> reason = null)
        {
            ICursor cursor = null;

            try
            {
                //on pre-Kitkat devices, we can't write content:// files
                if (!IsKitKatOrLater)
                {
                    Kp2aLog.Log("File is read-only because we're not on KitKat or later.");
                    if (reason != null)
                    {
                        reason.Result = UiStringKey.ReadOnlyReason_PreKitKat;
                    }
                    return(true);
                }


                //KitKat or later...
                var uri = Android.Net.Uri.Parse(ioc.Path);
                cursor = _ctx.ContentResolver.Query(uri, null, null, null, null, null);

                if (cursor != null && cursor.MoveToFirst())
                {
                    int column = cursor.GetColumnIndex(DocumentsContract.Document.ColumnFlags);
                    if (column < 0)
                    {
                        return(false);                        //seems like this is not supported. See below for reasoning to return false.
                    }
                    int flags = cursor.GetInt(column);
                    Kp2aLog.Log("File flags: " + flags);
                    if ((flags & (long)DocumentContractFlags.SupportsWrite) == 0)
                    {
                        if (reason != null)
                        {
                            reason.Result = UiStringKey.ReadOnlyReason_ReadOnlyFlag;
                        }
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    throw new Exception("couldn't move to first result element: " + (cursor == null) + uri.ToString());
                }
            }
            catch (Exception e)
            {
                Kp2aLog.LogUnexpectedError(e);
                //better return false here. We don't really know what happened (as this is unexpected).
                //let the user try to write the file. If it fails they will get an exception string.
                return(false);
            }
            finally
            {
                if (cursor != null)
                {
                    cursor.Close();
                }
            }
        }
Beispiel #15
0
 public void OnResume(IFileStorageSetupActivity activity)
 {
     Kp2aLog.Log("JFS/OnResume Ioc.Path=" + activity.Ioc.Path + ". Path=" + ((IJavaFileStorageFileStorageSetupActivity)activity).Path);
     _jfs.OnResume(((IJavaFileStorageFileStorageSetupActivity)activity));
 }
Beispiel #16
0
 public virtual void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
 {
     Kp2aLog.Log("StartSelectFile " + protocolId);
     _jfs.StartSelectFile((IJavaFileStorageFileStorageSetupInitiatorActivity)activity, isForSave, requestCode);
 }
Beispiel #17
0
        private List <Dataset> BuildEntryDatasets(string query, string queryDomain, string queryPackage, AutofillId[] autofillIds, StructureParser parser,
                                                  DisplayWarning warning, IList <InlinePresentationSpec> inlinePresentationSpecs)
        {
            List <Dataset> result = new List <Dataset>();

            Kp2aLog.Log("AF: BuildEntryDatasets");
            var suggestedEntries = GetSuggestedEntries(query).ToDictionary(e => e.DatasetName, e => e);

            Kp2aLog.Log("AF: BuildEntryDatasets found " + suggestedEntries.Count + " entries");
            int count = 0;

            foreach (var filledAutofillFieldCollection in suggestedEntries.Values)
            {
                if (filledAutofillFieldCollection == null)
                {
                    continue;
                }

                var inlinePresentationSpec = AutofillHelper.ExtractSpec(inlinePresentationSpecs, count);

                if (warning == DisplayWarning.None)
                {
                    FilledAutofillFieldCollection partitionData =
                        AutofillHintsHelper.FilterForPartition(filledAutofillFieldCollection, parser.AutofillFields.FocusedAutofillCanonicalHints);

                    Kp2aLog.Log("AF: Add dataset");

                    result.Add(AutofillHelper.NewDataset(this, parser.AutofillFields, partitionData, IntentBuilder,
                                                         inlinePresentationSpec));
                }
                else
                {
                    //return an "auth" dataset (actually for just warning the user in case domain/package dont match)
                    IntentSender sender =
                        IntentBuilder.GetAuthIntentSenderForWarning(this, query, queryDomain, queryPackage, warning);
                    var datasetName = filledAutofillFieldCollection.DatasetName;
                    if (datasetName == null)
                    {
                        Kp2aLog.Log("AF: dataset name is null");
                        continue;
                    }

                    RemoteViews presentation =
                        AutofillHelper.NewRemoteViews(PackageName, datasetName, AppNames.LauncherIcon);

                    var datasetBuilder = new Dataset.Builder(presentation);
                    datasetBuilder.SetAuthentication(sender);

                    AutofillHelper.AddInlinePresentation(this, inlinePresentationSpec, datasetName, datasetBuilder, AppNames.LauncherIcon);

                    //need to add placeholders so we can directly fill after ChooseActivity
                    foreach (var autofillId in autofillIds)
                    {
                        datasetBuilder.SetValue(autofillId, AutofillValue.ForText("PLACEHOLDER"));
                    }
                    Kp2aLog.Log("AF: Add auth dataset");
                    result.Add(datasetBuilder.Build());
                }
                count++;
            }

            return(result);
        }
Beispiel #18
0
        public override void OnFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback)
        {
            bool isManual = (request.Flags & FillRequest.FlagManualRequest) != 0;

            CommonUtil.logd("onFillRequest " + (isManual ? "manual" : "auto"));
            var structure = request.FillContexts.Last().Structure;


            if (_lockTime + _lockTimeout < DateTime.Now)
            {
                _lockTime = DateTime.Now;

                //TODO support package signature verification as soon as this is supported in Keepass storage

                var clientState = request.ClientState;
                CommonUtil.logd("onFillRequest(): data=" + CommonUtil.BundleToString(clientState));


                cancellationSignal.CancelEvent += (sender, e) =>
                {
                    Kp2aLog.Log("Cancel autofill not implemented yet.");
                    _lockTime = DateTime.MinValue;
                };
                // Parse AutoFill data in Activity
                StructureParser.AutofillTargetId query = null;
                var parser = new StructureParser(this, structure);
                try
                {
                    query = parser.ParseForFill(isManual);
                }
                catch (Java.Lang.SecurityException e)
                {
                    Log.Warn(CommonUtil.Tag, "Security exception handling request");
                    callback.OnFailure(e.Message);
                    return;
                }

                AutofillFieldMetadataCollection autofillFields           = parser.AutofillFields;
                InlineSuggestionsRequest        inlineSuggestionsRequest = null;
                IList <InlinePresentationSpec>  inlinePresentationSpecs  = null;
                if (((int)Build.VERSION.SdkInt >= 30) &&
                    (PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.InlineSuggestions_key), true)))
                {
                    inlineSuggestionsRequest = request.InlineSuggestionsRequest;

                    inlinePresentationSpecs = inlineSuggestionsRequest?.InlinePresentationSpecs;
                }


                var autofillIds = autofillFields.GetAutofillIds();
                if (autofillIds.Length != 0 && CanAutofill(query, isManual))
                {
                    var responseBuilder = new FillResponse.Builder();

                    bool hasEntryDataset = false;

                    IList <Dataset> entryDatasets = new List <Dataset>();
                    if (query.IncompatiblePackageAndDomain == false)
                    {
                        Kp2aLog.Log("AF: (query.IncompatiblePackageAndDomain == false)");
                        //domain and package are compatible. Use Domain if available and package otherwise. Can fill without warning.
                        entryDatasets = BuildEntryDatasets(query.DomainOrPackage, query.WebDomain,
                                                           query.PackageName,
                                                           autofillIds, parser, DisplayWarning.None,
                                                           inlinePresentationSpecs
                                                           ).Where(ds => ds != null).ToList();
                        if (entryDatasets.Count > inlineSuggestionsRequest?.MaxSuggestionCount - 2 /*disable dataset and query*/)
                        {
                            //we have too many elements. disable inline suggestions
                            inlinePresentationSpecs = null;
                            entryDatasets           = BuildEntryDatasets(query.DomainOrPackage, query.WebDomain,
                                                                         query.PackageName,
                                                                         autofillIds, parser, DisplayWarning.None,
                                                                         null
                                                                         ).Where(ds => ds != null).ToList();
                        }
                        foreach (var entryDataset in entryDatasets
                                 )
                        {
                            Kp2aLog.Log("AF: Got EntryDataset " + (entryDataset == null));
                            responseBuilder.AddDataset(entryDataset);
                            hasEntryDataset = true;
                        }
                    }



                    {
                        if (query.WebDomain != null)
                        {
                            AddQueryDataset(query.WebDomain,
                                            query.WebDomain, query.PackageName,
                                            isManual, autofillIds, responseBuilder, !hasEntryDataset,
                                            query.IncompatiblePackageAndDomain
                                    ? DisplayWarning.FillDomainInUntrustedApp
                                    : DisplayWarning.None,
                                            AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count));
                        }
                        else
                        {
                            AddQueryDataset(query.PackageNameWithPseudoSchema,
                                            query.WebDomain, query.PackageName,
                                            isManual, autofillIds, responseBuilder, !hasEntryDataset, DisplayWarning.None,
                                            AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count));
                        }
                    }

                    if (!PreferenceManager.GetDefaultSharedPreferences(this)
                        .GetBoolean(GetString(Resource.String.NoAutofillDisabling_key), false))
                    {
                        AddDisableDataset(query.DomainOrPackage, autofillIds, responseBuilder, isManual, AutofillHelper.ExtractSpec(inlinePresentationSpecs, entryDatasets.Count));
                    }

                    if (PreferenceManager.GetDefaultSharedPreferences(this)
                        .GetBoolean(GetString(Resource.String.OfferSaveCredentials_key), true))
                    {
                        if (!CompatBrowsers.Contains(parser.PackageId))
                        {
                            responseBuilder.SetSaveInfo(new SaveInfo.Builder(parser.AutofillFields.SaveType,
                                                                             parser.AutofillFields.GetAutofillIds()).Build());
                        }
                    }

                    Kp2aLog.Log("return autofill success");
                    callback.OnSuccess(responseBuilder.Build());
                }
                else
                {
                    Kp2aLog.Log("cannot autofill");
                    callback.OnSuccess(null);
                }
            }
            else
            {
                Kp2aLog.Log("Ignoring onFillRequest as there is another request going on.");
            }
        }
Beispiel #19
0
 public static void loge(string s)
 {
     Kp2aLog.Log(s);
 }
        // public void Save(string strFile, PwGroup pgDataSource, KdbxFormat fmt,
        //	IStatusLogger slLogger)
        // {
        //	bool bMadeUnhidden = UrlUtil.UnhideFile(strFile);
        //
        //	IOConnectionInfo ioc = IOConnectionInfo.FromPath(strFile);
        //	this.Save(IOConnection.OpenWrite(ioc), pgDataSource, format, slLogger);
        //
        //	if(bMadeUnhidden) UrlUtil.HideFile(strFile, true); // Hide again
        // }

        /// <summary>
        /// Save the contents of the current <c>PwDatabase</c> to a KDBX file.
        /// </summary>
        /// <param name="sSaveTo">Stream to write the KDBX file into.</param>
        /// <param name="pgDataSource">Group containing all groups and
        /// entries to write. If <c>null</c>, the complete database will
        /// be written.</param>
        /// <param name="fmt">Format of the file to create.</param>
        /// <param name="slLogger">Logger that recieves status information.</param>
        public void Save(Stream sSaveTo, PwGroup pgDataSource, KdbxFormat fmt,
                         IStatusLogger slLogger)
        {
            Debug.Assert(sSaveTo != null);
            if (sSaveTo == null)
            {
                throw new ArgumentNullException("sSaveTo");
            }

            if (m_bUsedOnce)
            {
                throw new InvalidOperationException("Do not reuse KdbxFile objects!");
            }
            m_bUsedOnce = true;

            m_format   = fmt;
            m_slLogger = slLogger;

            PwGroup      pgRoot   = (pgDataSource ?? m_pwDatabase.RootGroup);
            UTF8Encoding encNoBom = StrUtil.Utf8;
            CryptoRandom cr       = CryptoRandom.Instance;

            byte[] pbCipherKey = null;
            byte[] pbHmacKey64 = null;

            m_pbsBinaries.Clear();
            m_pbsBinaries.AddFrom(pgRoot);

            List <Stream> lStreams = new List <Stream>();

            lStreams.Add(sSaveTo);

            HashingStreamEx sHashing = new HashingStreamEx(sSaveTo, true, null);

            lStreams.Add(sHashing);

            try
            {
                m_uFileVersion = GetMinKdbxVersion();

                int           cbEncKey, cbEncIV;
                ICipherEngine iCipher = GetCipher(out cbEncKey, out cbEncIV);

                m_pbMasterSeed   = cr.GetRandomBytes(32);
                m_pbEncryptionIV = cr.GetRandomBytes((uint)cbEncIV);

                // m_pbTransformSeed = cr.GetRandomBytes(32);
                PwUuid    puKdf = m_pwDatabase.KdfParameters.KdfUuid;
                KdfEngine kdf   = KdfPool.Get(puKdf);
                if (kdf == null)
                {
                    throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
                                        // KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
                                        "UUID: " + puKdf.ToHexString() + ".");
                }
                kdf.Randomize(m_pwDatabase.KdfParameters);

                if (m_format == KdbxFormat.Default)
                {
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.Salsa20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(32);
                    }
                    else             // KDBX >= 4
                    {
                        m_craInnerRandomStream   = CrsAlgorithm.ChaCha20;
                        m_pbInnerRandomStreamKey = cr.GetRandomBytes(64);
                    }

                    m_randomStream = new CryptoRandomStream(m_craInnerRandomStream,
                                                            m_pbInnerRandomStreamKey);
                }

                if (m_uFileVersion < FileVersion32_4)
                {
                    m_pbStreamStartBytes = cr.GetRandomBytes(32);
                }

                Stream sXml;
                if (m_format == KdbxFormat.Default || m_format == KdbxFormat.ProtocolBuffers)
                {
                    byte[] pbHeader = GenerateHeader();
                    m_pbHashOfHeader = CryptoUtil.HashSha256(pbHeader);

                    MemUtil.Write(sHashing, pbHeader);
                    sHashing.Flush();

                    ComputeKeys(out pbCipherKey, cbEncKey, out pbHmacKey64);

                    Stream sPlain;
                    if (m_uFileVersion < FileVersion32_4)
                    {
                        Stream sEncrypted = EncryptStream(sHashing, iCipher,
                                                          pbCipherKey, cbEncIV, true);
                        if ((sEncrypted == null) || (sEncrypted == sHashing))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                        lStreams.Add(sEncrypted);

                        MemUtil.Write(sEncrypted, m_pbStreamStartBytes);

                        sPlain = new HashedBlockStream(sEncrypted, true);
                    }
                    else                     // KDBX >= 4
                    {
                        // For integrity checking (without knowing the master key)
                        MemUtil.Write(sHashing, m_pbHashOfHeader);

                        byte[] pbHeaderHmac = ComputeHeaderHmac(pbHeader, pbHmacKey64);
                        MemUtil.Write(sHashing, pbHeaderHmac);

                        Stream sBlocks = new HmacBlockStream(sHashing, true,
                                                             true, pbHmacKey64);
                        lStreams.Add(sBlocks);

                        sPlain = EncryptStream(sBlocks, iCipher, pbCipherKey,
                                               cbEncIV, true);
                        if ((sPlain == null) || (sPlain == sBlocks))
                        {
                            throw new SecurityException(KLRes.CryptoStreamFailed);
                        }
                    }
                    lStreams.Add(sPlain);

                    if (m_pwDatabase.Compression == PwCompressionAlgorithm.GZip)
                    {
                        sXml = new GZipStream(sPlain, CompressionMode.Compress);
                        lStreams.Add(sXml);
                    }
                    else
                    {
                        sXml = sPlain;
                    }

                    if (m_uFileVersion >= FileVersion32_4)
                    {
                        WriteInnerHeader(sXml);                         // Binary header before XML
                    }
                }
                else if (m_format == KdbxFormat.PlainXml)
                {
                    sXml = sHashing;
                }
                else
                {
                    Debug.Assert(false);
                    throw new ArgumentOutOfRangeException("fmt");
                }

                var stopWatch = Stopwatch.StartNew();

                if (m_format == KdbxFormat.ProtocolBuffers)
                {
                    KdbpFile.WriteDocument(m_pwDatabase, sXml, m_pbInnerRandomStreamKey, m_pbHashOfHeader);
                }
                else
                {
#if KeePassUAP
                    XmlWriterSettings xws = new XmlWriterSettings();
                    xws.Encoding            = encNoBom;
                    xws.Indent              = true;
                    xws.IndentChars         = "\t";
                    xws.NewLineOnAttributes = false;

                    XmlWriter xw = XmlWriter.Create(sXml, xws);
#else
                    XmlTextWriter xw = new XmlTextWriter(sXml, encNoBom);

                    xw.Formatting  = Formatting.Indented;
                    xw.IndentChar  = '\t';
                    xw.Indentation = 1;
#endif
                    m_xmlWriter = xw;

                    WriteDocument(pgRoot);

                    m_xmlWriter.Flush();
                    m_xmlWriter.Close();
                }
                Kp2aLog.Log(String.Format("{1}: {0}ms", stopWatch.ElapsedMilliseconds, m_format == KdbxFormat.ProtocolBuffers ? "KdbpFile.WriteDocument" : "Xml WriteDocument"));
            }
            finally
            {
                if (pbCipherKey != null)
                {
                    MemUtil.ZeroByteArray(pbCipherKey);
                }
                if (pbHmacKey64 != null)
                {
                    MemUtil.ZeroByteArray(pbHmacKey64);
                }

                CommonCleanUpWrite(lStreams, sHashing);
            }
        }
Beispiel #21
0
            public IDriveItemRequestBuilder getPathItem()
            {
                Kp2aLog.Log("getPathItem for " + itemLocation.ToString());
                IDriveItemRequestBuilder pathItem;

                if (!hasShare())
                {
                    throw new Exception("Cannot get path item without share");
                }
                if ("me".Equals(itemLocation.Share.Id))
                {
                    if (verbose)
                    {
                        Kp2aLog.Log("Path share is me");
                    }


                    if (_specialFolder == null)
                    {
                        if (verbose)
                        {
                            Kp2aLog.Log("No special folder. Use drive root.");
                        }
                        pathItem = client.Me.Drive.Root;
                    }
                    else
                    {
                        if (verbose)
                        {
                            Kp2aLog.Log("Special folder = " + _specialFolder);
                        }
                        pathItem = client.Me.Drive.Special[_specialFolder];
                    }

                    if (itemLocation.LocalPath.Any())
                    {
                        if (verbose)
                        {
                            Kp2aLog.Log("LocalPath = " + itemLocation.LocalPathString);
                        }
                        pathItem = pathItem.ItemWithPath(itemLocation.LocalPathString);
                    }
                }
                else
                {
                    if (verbose)
                    {
                        Kp2aLog.Log("Path share is not me");
                    }
                    if (!itemLocation.LocalPath.Any())
                    {
                        String webUrl = itemLocation.Share.WebUrl;
                        if (verbose)
                        {
                            Kp2aLog.Log("Share WebUrl = " + webUrl);
                        }
                        var encodedShareId = CalculateEncodedShareId(webUrl);
                        return(client.Shares[encodedShareId].Root);
                    }

                    /*String webUrl = itemLocation.Share.WebUrl;
                     * if ("".Equals(itemLocation.LocalPath) == false)
                     * {
                     *  if (!webUrl.EndsWith("/")) webUrl += "/";
                     *  webUrl += itemLocation.LocalPath;
                     * }
                     * Android.Util.Log.Debug("KP2A","webUrl = " + Encoding.UTF8.GetBytes(webUrl));
                     * //calculate shareid according to https://docs.microsoft.com/en-us/graph/api/shares-get?view=graph-rest-1.0&tabs=java
                     * var encodedShareId = CalculateEncodedShareId(webUrl);
                     * Android.Util.Log.Debug("KP2A", "encodedShareId = " + encodedShareId);
                     * pathItem = client.Shares[encodedShareId].Root;
                     */
                    if (verbose)
                    {
                        Kp2aLog.Log("Using driveId=" + itemLocation.DriveId + " and item id=" + itemLocation.LocalPath.Last().Id);
                    }
                    return(client.Drives[itemLocation.DriveId].Items[itemLocation.LocalPath.Last().Id]);
                }


                return(pathItem);
            }
        public void TestLoadEditSaveWhenModified()
        {
            //create the default database:
            IKp2aApp app = SetupAppWithDefaultDatabase();

            IOConnection.DeleteFile(new IOConnectionInfo {
                Path = DefaultFilename
            });
            //save it and reload it so we have a base version
            SaveDatabase(app);
            app = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app c: " + group.Name);
            }

            //load once more:
            var app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            //modifiy once:
            PwGroup group2 = new PwGroup(true, true, "TestGroup2", PwIcon.Apple);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group2, true);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app b: " + group.Name);
            }

            SaveDatabase(app2);

            _testCacheSupervisor.Reset();

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app d: " + group.Name);
            }
            Assert.IsNull(((TestKp2aApp)app).LastYesNoCancelQuestionTitle);
            _testCacheSupervisor.AssertNoCall();

            //modify the database by adding a group:
            PwGroup group1 = new PwGroup(true, true, "TestGroup", PwIcon.Apple);

            app.GetDb().KpDatabase.RootGroup.AddGroup(group1, true);

            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app a: " + group.Name);
            }


            //save the database again:
            _testCacheSupervisor.Reset();
            SaveDatabase(app);
            Assert.AreEqual(((TestKp2aApp)app).LastYesNoCancelQuestionTitle, UiStringKey.TitleSyncQuestion);
            _testCacheSupervisor.AssertNoCall();


            //load database to a new app instance:
            IKp2aApp resultApp = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);

            app2.GetDb().KpDatabase.RootGroup.AddGroup(group1, true);
            foreach (var group in app.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("app: " + group.Name);
            }

            foreach (var group in resultApp.GetDb().KpDatabase.RootGroup.Groups)
            {
                Kp2aLog.Log("resultApp: " + group.Name);
            }

            //ensure the change was saved:
            AssertDatabasesAreEqual(app2.GetDb().KpDatabase, resultApp.GetDb().KpDatabase);
        }
Beispiel #23
0
        private static IOWebClient CreateWebClient(IOConnectionInfo ioc, bool digestAuth)
        {
            PrepareWebAccess();

            IOWebClient wc = new IOWebClient();

            ConfigureWebClient(wc);

            if ((ioc.UserName.Length > 0) || (ioc.Password.Length > 0))
            {
                //set the credentials without a cache (in case the cache below fails:

                //check for backslash to determine whether we need to specify the domain:
                int backslashPos = ioc.UserName.IndexOf("\\", StringComparison.Ordinal);
                if (backslashPos > 0)
                {
                    string domain = ioc.UserName.Substring(0, backslashPos);
                    string user   = ioc.UserName.Substring(backslashPos + 1);
                    wc.Credentials = new NetworkCredential(user, ioc.Password, domain);
                }
                else
                {
                    wc.Credentials = new NetworkCredential(ioc.UserName, ioc.Password);
                }


                if (digestAuth)
                {
                    //try to use the credential cache to access with Digest support:
                    try
                    {
                        var credentialCache = new CredentialCache();

                        credentialCache.Add(
                            new Uri(new Uri(ioc.Path).GetLeftPart(UriPartial.Authority)),
                            "Digest",
                            new NetworkCredential(ioc.UserName, ioc.Password)
                            );

                        credentialCache.Add(
                            new Uri(new Uri(ioc.Path).GetLeftPart(UriPartial.Authority)),
                            "NTLM",
                            new NetworkCredential(ioc.UserName, ioc.Password)
                            );


                        wc.Credentials = credentialCache;
                    } catch (NotImplementedException e)
                    {
                        Kp2aLog.Log(e.ToString());
                    } catch (Exception e)
                    {
                        Kp2aLog.LogUnexpectedError(e);
                        Debug.Assert(false);
                    }
                }
            }
            else if (NativeLib.IsUnix())            // Mono requires credentials
            {
                wc.Credentials = new NetworkCredential("anonymous", string.Empty);
            }

            return(wc);
        }
Beispiel #24
0
 public void SetMessage(string resourceString)
 {
     Kp2aLog.Log("Progress message: " + resourceString);
 }