Update wrt-security_0.0.42
[framework/web/wrt-security.git] / popup_process / PopupInvoker.cpp
1 /*
2  * Copyright (c) 2011 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
17 #include "PopupInvoker.h"
18 #include <sstream>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <dpl/log/log.h>
22 #include <dpl/waitable_handle.h>
23 #include <dpl/binary_queue.h>
24 #include <dpl/serialization.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include "PopupEnum.h"
28 #include "PopupSerializer.h"
29 #include "security_daemon_dbus_config.h"
30 #include "popup_response_server_api.h"
31
32 namespace {
33 const char *POPUP_EXEC = "/usr/bin/wrt-popup";
34 }
35
36 PopupInvoker::PopupInvoker() :
37     m_inputName(tmpnam(NULL)),
38     m_outputName(tmpnam(NULL))
39 {
40     Try
41     {
42         m_input.Create(m_inputName);
43         m_output.Create(m_outputName);
44         LogDebug("Pipes created");
45     }
46     Catch (DPL::Exception)
47     {
48         LogError("Cannot create pipes");
49     }
50 }
51
52 PopupInvoker::~PopupInvoker()
53 {
54     Try
55     {
56         m_input.Destroy(m_inputName);
57         m_output.Destroy(m_outputName);
58         LogDebug("Pipes destroyed");
59     }
60     Catch (DPL::Exception)
61     {
62         LogError("Cannot destroy pipes");
63     }
64 }
65
66 bool PopupInvoker::showSyncPopup(int popupType, const AceUserdata& aceData)
67 {
68     Try
69     {
70         DPL::BinaryQueue data;
71         PopupSerializer::appendArg(ACE_PROMPT, data);
72         PopupSerializer::appendArg(popupType, data);
73         PopupSerializer::appendArg(aceData.resource, data);
74         DPL::NamedInputPipe tmp;
75         tmp.Open(m_outputName);
76         m_output.Open(m_outputName);
77         m_input.Open(m_inputName);
78         m_output.Write(data, data.Size());
79
80         executePopup();
81
82         //Result from popup application is available. Read it.
83         DPL::BinaryQueueAutoPtr resultData =
84             m_input.Read(std::numeric_limits<std::size_t>::max());
85         const int result = PopupSerializer::getIntArg(*resultData);
86         const int validity = PopupSerializer::getIntArg(*resultData);
87
88         Assert(resultData->Empty());
89
90         tmp.Close();
91         m_input.Close();
92         m_output.Close();
93
94         Prompt::PromptAnswer answer(result,
95                                     static_cast<Prompt::Validity>(validity));
96
97         LogDebug("Answer: " << result << " Validity: " << validity);
98
99         //ASK SECURITY DAEMON
100         if (!result &&
101             Prompt::Validity::ONCE == answer.getValidity())
102         {
103             LogInfo("User answer is DENY ONCE. Don't call security daemon");
104         }
105         else
106         {
107             LogInfo("calling security daemon");
108             bool securityResponse =
109                     securityDaemonCall(answer.isAccessAllowed(),
110                                        answer.getValidity(),
111                                        aceData);
112
113             if(!securityResponse)
114             {
115                 LogError("Security Daemon has responded with false!");
116                 return false;
117             }
118             LogInfo("Security Daemon has responded with true");
119         }
120
121         return answer.isAccessAllowed();
122     }
123     Catch(DPL::Exception)
124     {
125         LogError("error occured");
126     }
127     // if error then return deny once
128     return false;
129 }
130
131 bool PopupInvoker::askYesNo(const std::string& title, const std::string& message)
132 {
133     Try
134     {
135         DPL::BinaryQueue data;
136         PopupSerializer::appendArg(YES_NO_PROMPT, data);
137         PopupSerializer::appendArg(title, data);
138         PopupSerializer::appendArg(message, data);
139         DPL::NamedInputPipe tmp;
140         tmp.Open(m_outputName);
141         m_output.Open(m_outputName);
142         m_input.Open(m_inputName);
143         m_output.Write(data, data.Size());
144
145         executePopup();
146
147         //Result from popup application is available. Read it.
148         DPL::BinaryQueueAutoPtr resultData =
149             m_input.Read(std::numeric_limits<std::size_t>::max());
150         const int result = PopupSerializer::getIntArg(*resultData);
151
152         LogDebug("Popup result is: " << result);
153
154         Assert(resultData->Empty());
155
156         tmp.Close();
157         m_input.Close();
158         m_output.Close();
159
160         return (!!result);
161     }
162     Catch(DPL::Exception)
163     {
164         LogError("error occured");
165     }
166
167     return false;
168 }
169
170 void PopupInvoker::executePopup()
171 {
172     pid_t pid = fork();
173     if (pid == -1)
174     {
175         //error occured
176         LogError("Cannot display popup!");
177         Assert(false);
178     }
179     if (pid == 0)
180     {
181         //child process
182         int ret = execl(POPUP_EXEC,
183                         POPUP_EXEC,
184                         m_outputName.c_str(),
185                         m_inputName.c_str(),
186                         NULL);
187         if (ret == -1) {
188             //execl returns -1 on error
189             LogError("Cannot display popup!");
190             Assert(false);
191         }
192     }
193
194     DPL::WaitableHandle handle = m_input.WaitableReadHandle();
195     DPL::WaitForSingleHandle(handle);
196 }
197
198 bool PopupInvoker::securityDaemonCall(bool allowed,
199                                            Prompt::Validity valid,
200                                            const AceUserdata &data)
201 {
202     if(!m_dbusPopupClient)
203         m_dbusPopupClient.Reset(new DPL::DBus::Client(
204                     WrtSecurity::SecurityDaemonConfig::OBJECT_PATH(),
205                     WrtSecurity::SecurityDaemonConfig::SERVICE_NAME(),
206                     WrtSecurity::PopupServerApi::INTERFACE_NAME()));
207
208     bool response = false;
209     Try {
210         m_dbusPopupClient->call(
211                 WrtSecurity::PopupServerApi::VALIDATION_METHOD(),
212                        allowed,
213                        static_cast<int>(valid),
214                        data.handle,
215                        data.subject,
216                        data.resource,
217                        data.paramKeys,
218                        data.paramValues,
219                        data.sessionId,
220                        &response);
221     } Catch (DPL::DBus::Client::Exception::DBusClientException) {
222         ReThrowMsg(PopupInvoker::Exception::PopupInvokerException,
223                  "Failed to call security daemon");
224     }
225
226     return response;
227 }