Fix coverity issue
[platform/core/security/ode.git] / fota / fota.cpp
1 /*
2  *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <strings.h>
22 #include <blkid.h>
23
24 #include <string>
25 #include <iostream>
26
27 #include <klay/audit/dlog-sink.h>
28
29 #include <upgrade-support.h>
30 #include <internal-encryption-common.h>
31 #include <engine/encryption/dmcrypt-engine.h>
32
33 audit::LogSink *SINK = nullptr;
34
35 namespace ode {
36
37 struct AbstractDevice {
38         AbstractDevice() {}
39         virtual ~AbstractDevice() {}
40         virtual std::string findNode(const std::string &name) = 0;
41 };
42
43 struct MmcDevice : public AbstractDevice {
44 public:
45         MmcDevice(int id) : device("/dev/mmcblk" + std::to_string(id)), deviceHandle(-1)
46         {
47                 deviceHandle = ::open(device.c_str(), O_RDONLY);
48                 if (deviceHandle == -1)
49                         throw std::runtime_error("Invalid device: " + device);
50         }
51
52         virtual ~MmcDevice()
53         {
54                 if (deviceHandle != -1)
55                         ::close(deviceHandle);
56         }
57
58         virtual std::string findNode(const std::string &name)
59         {
60                 blkid_partlist partlist;
61                 blkid_probe probe;
62                 int partno = 0;
63
64                 probe = ::blkid_new_probe();
65                 if (!probe) {
66                         throw std::runtime_error("Failed to call blkid_new_probe");
67                 }
68
69                 if (::blkid_probe_set_device(probe, deviceHandle, 0, 0) < 0) {
70                         ::blkid_free_probe(probe);
71                         throw std::runtime_error("Failed to set prove device: " + device);
72                 }
73
74                 partlist = ::blkid_probe_get_partitions(probe);
75                 if (!partlist) {
76                         ::blkid_free_probe(probe);
77                         throw std::runtime_error("Failed to get partition list in device: " + device);
78                 }
79
80                 int num = ::blkid_partlist_numof_partitions(partlist);
81                 for (int i = 1; i <= num; i++) {
82                         blkid_partition par = ::blkid_partlist_get_partition(partlist, i);
83
84                         const char *n = ::blkid_partition_get_name(par);
85                         if (!n)
86                                 break;
87
88                         if (::strcasecmp(n, name.c_str()) == 0) {
89                                 partno = ::blkid_partition_get_partno(par);
90                                 break;
91                         }
92                 }
93
94                 ::blkid_free_probe(probe);
95
96                 if (partno <= 0) {
97                         throw std::runtime_error("Failed to get partition number with " +  name);
98                 }
99
100                 return device + "p" + std::to_string(partno);
101         }
102
103 private:
104         std::string device;
105         int deviceHandle;
106 };
107
108 // dummy implementation
109 ProgressBar::ProgressBar(UpdateFunc const&) : updateValue(0) {}
110 ProgressBar::~ProgressBar() {}
111
112 void ProgressBar::update(unsigned) {}
113 void ProgressBar::done(void) {}
114
115 } // namespace ode
116
117 namespace {
118
119 const std::string MOUNT = "mount";
120 const std::string UMOUNT = "umount";
121 const std::string REMOVE = "remove";
122
123 void usage()
124 {
125         std::cout <<
126                 "Usage: ode-fota [Operation]" << std::endl <<
127                 std::endl <<
128                 "Operations :" << std::endl <<
129                 "  mount [path]   Mount internal memory using stored master key" << std::endl <<
130                 "  umount [path]  Unmount internal memory" << std::endl <<
131                 "  remove         Remove stored internal memory master key" << std::endl;
132 }
133
134 } // anonymous namespace
135
136 int main(int argc, char* argv[])
137 {
138         try {
139                 using namespace ode;
140
141                 if (argc < 2 || argc > 3) {
142                         usage();
143                         return EXIT_FAILURE;
144                 }
145
146                 MmcDevice dev(0);
147                 std::string devpath = dev.findNode("user");
148
149                 if (MOUNT == argv[1]) {
150                         auto masterKey = UpgradeSupport::loadMasterKey(devpath);
151                         std::string path = INTERNAL_PATH;
152                         if (argc == 3)
153                                 path = argv[2];
154
155                         DMCryptEngine dmcrypt(devpath, path, ProgressBar([](unsigned){}));
156
157                         // mount options are ignored by mount()
158                         dmcrypt.mount(masterKey, 0);
159                         UpgradeSupport::createUpgradeFlag();
160                 } else if (UMOUNT == argv[1]) {
161                         std::string path = INTERNAL_PATH;
162                         if (argc == 3)
163                                 path = argv[2];
164
165                         DMCryptEngine dmcrypt(devpath, path, ProgressBar([](int){}));
166                         dmcrypt.umount();
167                 } else if (REMOVE == argv[1]) {
168                         UpgradeSupport::removeMasterKey(devpath);
169                 } else {
170                         usage();
171                         return EXIT_FAILURE;
172                 }
173                 return EXIT_SUCCESS;
174         } catch (const std::exception& e) {
175                 std::cerr << e.what() << std::endl;
176         } catch (...) {
177                 std::cerr << "Unknown exception occured" << std::endl;
178         }
179
180         return EXIT_FAILURE;
181 }