aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java
blob: aa30e845d0d822a1a5330773694090fc077dcff1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
 * Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.sufficientlysecure.keychain.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.Blobs;
import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns;
import org.sufficientlysecure.keychain.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

public class KeychainServiceBlobProvider extends ContentProvider {
    private static final String STORE_PATH = Constants.Path.APP_DIR + "/KeychainBlobs";

    private KeychainServiceBlobDatabase mBlobDatabase = null;

    public KeychainServiceBlobProvider() {
        File dir = new File(STORE_PATH);
        dir.mkdirs();
    }

    @Override
    public boolean onCreate() {
        mBlobDatabase = new KeychainServiceBlobDatabase(getContext());
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Uri insert(Uri uri, ContentValues ignored) {
        // ContentValues are actually ignored, because we want to store a blob with no more
        // information but have to create an record with the password generated here first
        ContentValues vals = new ContentValues();

        // Insert a random key in the database. This has to provided by the caller when updating or
        // getting the blob
        String password = UUID.randomUUID().toString();
        vals.put(BlobsColumns.KEY, password);

        SQLiteDatabase db = mBlobDatabase.getWritableDatabase();
        long newRowId = db.insert(KeychainServiceBlobDatabase.TABLE, null, vals);
        Uri insertedUri = ContentUris.withAppendedId(Blobs.CONTENT_URI, newRowId);

        return Uri.withAppendedPath(insertedUri, password);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException,
            FileNotFoundException {
        Log.d(Constants.TAG, "openFile() called with uri: " + uri.toString() + " and mode: " + mode);

        List<String> segments = uri.getPathSegments();
        if (segments.size() < 2) {
            throw new SecurityException("Password not found in URI");
        }
        String id = segments.get(0);
        String key = segments.get(1);

        Log.d(Constants.TAG, "Got id: " + id + " and key: " + key);

        // get the data
        SQLiteDatabase db = mBlobDatabase.getReadableDatabase();
        Cursor result = db.query(KeychainServiceBlobDatabase.TABLE, new String[]{BaseColumns._ID},
                BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?",
                new String[]{id, key}, null, null, null);

        if (result.getCount() == 0) {
            // either the key is wrong or no id exists
            throw new FileNotFoundException("No file found with that ID and/or password");
        }

        File targetFile = new File(STORE_PATH, id);
        if (mode.equals("w")) {
            Log.d(Constants.TAG, "Try to open file w");
            if (!targetFile.exists()) {
                try {
                    targetFile.createNewFile();
                } catch (IOException e) {
                    Log.e(Constants.TAG, "Got IEOException on creating new file", e);
                    throw new FileNotFoundException("Could not create file to write to");
                }
            }
            return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_WRITE_ONLY
                    | ParcelFileDescriptor.MODE_TRUNCATE);
        } else if (mode.equals("r")) {
            Log.d(Constants.TAG, "Try to open file r");
            if (!targetFile.exists()) {
                throw new FileNotFoundException("Error: Could not find the file requested");
            }
            return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY);
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getType(Uri uri) {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder) {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }

}