<label name="security-server::api-password-check" />
<label name="security-server::api-password-set" />
<label name="security-server::api-password-reset" />
+ <label name="security-server::api-open-for" />
<label name="security-server::audit-files" />
</provide>
</define>
/*! \brief indicating getting smack label from socket failed */
#define SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED -21
+/*! \brief indicating getting smack label from file failed */
+#define SECURITY_SERVER_API_ERROR_GETTING_FILE_LABEL_FAILED -22
+
+/*! \brief indicating setting smack label for file failed */
+#define SECURITY_SERVER_API_ERROR_SETTING_FILE_LABEL_FAILED -23
+
+/*! \brief indicating file already exists */
+#define SECURITY_SERVER_API_ERROR_FILE_EXIST -24
+
+/*! \brief indicating file does not exist */
+#define SECURITY_SERVER_API_ERROR_FILE_NOT_EXIST -25
+
+/*! \brief indicating file open error */
+#define SECURITY_SERVER_API_ERROR_FILE_OPEN_FAILED -26
+
+/*! \brief indicating file creation error */
+#define SECURITY_SERVER_API_ERROR_FILE_CREATION_FAILED -27
+
+/*! \brief indicating file deletion error */
+#define SECURITY_SERVER_API_ERROR_FILE_DELETION_FAILED -28
+
/*! \brief indicating the error with unknown reason */
#define SECURITY_SERVER_API_ERROR_UNKNOWN -255
/** @}*/
*
* Access to this function requires SMACK rule: "<app_label> security-server::api-open-for w"
*/
-int security_server_open_for(const char *filename, int *fd);
+int security_server_open_for(const char *filename, int *fd) __attribute__((deprecated));
+/*
+ * This function allows to create, if doesn't exist, file by Security Server on
+ * behalf of calling process in secured directory. File gets smack label of
+ * designated client process, passed as 'client_label' argument, which is
+ * allowed to read created file.
+ *
+ * \param[in] File name to create
+ * \param[in] Label of designated client
+ * \param[out] File descriptor
+ *
+ * \return SECURITY_SERVER_API_SUCCESS on success or one of error codes on fail
+ * \return SECURITY_SERVER_API_ERROR_ACCESS_DENIED
+ * \return SECURITY_SERVER_API_ERROR_SOCKET
+ * \retrun SECURITY_SERVER_API_ERROR_INPUT_PARAM
+ * \return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_FILE_CREATION_FAILED
+ * \return SECURITY_SERVER_API_ERROR_SETTING_FILE_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_FILE_EXIST
+ *
+ * Access to this function requires SMACK rule: "<app_label> security-server::api-open-for w"
+ */
+int security_server_shared_file_open(const char *filename, const char *client_label, int *fd);
+
+/*
+ * This function allows to open existing file by Security Server on behalf of
+ * calling process in secured directory. Security Server checks smack label
+ * of calling process and if it's the same as file label access to file is
+ * granted.
+ *
+ * \param[in] File name to open
+ * \param[out] File descriptor
+ *
+ * \return SECURITY_SERVER_API_SUCCESS on success or one of error codes on fail
+ * \return SECURITY_SERVER_API_ERROR_ACCESS_DENIED
+ * \return SECURITY_SERVER_API_ERROR_SOCKET
+ * \return SECURITY_SERVER_API_ERROR_INPUT_PARAM
+ * \return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_GETTING_FILE_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED
+ * \return SECURITY_SERVER_API_ERROR_FILE_NOT_EXIST
+ *
+ * Access to this function requires SMACK rule: "<app_label> security-server::api-open-for w"
+ */
+int security_server_shared_file_reopen(const char *filename, int *fd);
+
+/*
+ * This function allows to delete existing file by Security Server on behalf of
+ * calling process in secured directory. Security Server checks smack label
+ * of calling process and if it's the same as file label data file is deleted.
+ *
+ * \param[in] File name to delete
+ *
+ * \return SECURITY_SERVER_API_SUCCESS on success or one of error codes on fail
+ * \return SECURITY_SERVER_API_ERROR_ACCESS_DENIED
+ * \return SECURITY_SERVER_API_ERROR_SOCKET
+ * \return SECURITY_SERVER_API_ERROR_INPUT_PARAM
+ * \return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_GETTING_FILE_LABEL_FAILED
+ * \return SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED
+ * \return SECURITY_SERVER_API_ERROR_FILE_DELETION_FAILED
+ * \return SECURITY_SERVER_API_ERROR_FILE_NOT_EXIST
+ *
+ * Access to this function requires SMACK rule: "<app_label> security-server::api-open-for w"
+ */
+int security_server_shared_file_delete(const char *filename);
#ifdef __cplusplus
}
* limitations under the License
*/
/*
- * @file client-open-for-cookie.cpp
+ * @file client-open-for.cpp
* @author Zbigniew Jasinski (z.jasinski@samsung.com)
* @version 1.0
* @brief This file contains implementation of security-server API
#include <security-server.h>
+namespace {
+
+void create_msghdr(struct msghdr* hdr,
+ struct iovec* iov,
+ unsigned char* cmsgbuf,
+ const size_t cmsgbufSize,
+ int* retcode)
+{
+ memset(hdr, 0, sizeof(struct msghdr));
+ memset(cmsgbuf, 0, cmsgbufSize);
+
+ iov->iov_base = retcode;
+ iov->iov_len = sizeof(*retcode);
+ hdr->msg_iov = iov;
+ hdr->msg_iovlen = 1;
+
+ if (NULL != cmsgbuf) {
+ hdr->msg_control = cmsgbuf;
+ hdr->msg_controllen = cmsgbufSize;
+ }
+}
+
+} // namespace anonymous
+
SECURITY_SERVER_API
int security_server_open_for(const char *filename, int *fd)
{
- using namespace SecurityServer;
- try {
- if (NULL == filename || std::string(filename).empty()) {
+ using namespace SecurityServer;
+ return try_catch([&] {
+ if (NULL == filename || !strlen(filename)) {
LogError("Error input param.");
return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
}
MessageBuffer send;
+ Serialization::Serialize(send, (int)OpenForHdrs::OPEN_DEPRECATED);
Serialization::Serialize(send, std::string(filename));
struct msghdr hdr;
struct iovec iov;
- struct cmsghdr *cmsg = NULL;
+ unsigned char cmsgbuf[CMSG_SPACE(sizeof(int))];
int retcode = -1;
- int result = -1;
+
+ create_msghdr(&hdr, &iov, &cmsgbuf[0], sizeof(cmsgbuf), &retcode);
+
+ int result = sendToServerAncData(SERVICE_SOCKET_OPEN_FOR, send.Pop(), hdr);
+ if (result != SECURITY_SERVER_API_SUCCESS) {
+ *fd = -1;
+ return result;
+ }
+
+ if (hdr.msg_flags & MSG_CTRUNC) {
+ LogError("Not enough space for ancillary element array.");
+ *fd = -1;
+ return SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ for(cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
+ if((SOL_SOCKET == cmsg->cmsg_level) && (SCM_RIGHTS == cmsg->cmsg_type)) {
+ memmove(fd, CMSG_DATA(cmsg), sizeof(int));
+ }
+ }
+
+ return retcode;
+ });
+}
+
+SECURITY_SERVER_API
+int security_server_shared_file_open(const char *filename, const char *client_label, int *fd)
+{
+ using namespace SecurityServer;
+ return try_catch([&] {
+ if ((NULL == filename || !strlen(filename) ||
+ (NULL == client_label || !strlen(client_label)))) {
+ LogError("Error input param.");
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+ }
+
+ MessageBuffer send;
+
+ Serialization::Serialize(send, (int)OpenForHdrs::OPEN);
+ Serialization::Serialize(send, std::string(filename));
+ Serialization::Serialize(send, std::string(client_label));
+
+ struct msghdr hdr;
+ struct iovec iov;
unsigned char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ int retcode = -1;
- memset(&hdr, 0, sizeof(struct msghdr));
- memset(cmsgbuf, 0, CMSG_SPACE(sizeof(int)));
+ create_msghdr(&hdr, &iov, &cmsgbuf[0], sizeof(cmsgbuf), &retcode);
- iov.iov_base = &retcode;
- iov.iov_len = sizeof(retcode);
- hdr.msg_iov = &iov;
- hdr.msg_iovlen = 1;
+ int result = sendToServerAncData(SERVICE_SOCKET_OPEN_FOR, send.Pop(), hdr);
+ if (result != SECURITY_SERVER_API_SUCCESS) {
+ *fd = -1;
+ return result;
+ }
- hdr.msg_control = cmsgbuf;
- hdr.msg_controllen = CMSG_SPACE(sizeof(int));
+ if (hdr.msg_flags & MSG_CTRUNC) {
+ LogError("Not enough space for ancillary element array.");
+ *fd = -1;
+ return SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ /*
+ * Since 'socket packet' can handle more than one control message
+ * we need to iterate through all ancillary data elements and check
+ * which one has our file desciptor (SCM_RIGHTS == cmsg->cmsg_type)
+ */
+ for(cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
+ if((SOL_SOCKET == cmsg->cmsg_level) && (SCM_RIGHTS == cmsg->cmsg_type)) {
+ memmove(fd, CMSG_DATA(cmsg), sizeof(int));
+ }
+ }
+
+ return retcode;
+ });
+}
+
+SECURITY_SERVER_API
+int security_server_shared_file_reopen(const char *filename, int *fd)
+{
+ using namespace SecurityServer;
+ return try_catch([&] {
+ if ((NULL == filename || !strlen(filename))) {
+ LogError("Error input param.");
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+ }
+
+ MessageBuffer send;
+
+ Serialization::Serialize(send, (int)OpenForHdrs::REOPEN);
+ Serialization::Serialize(send, std::string(filename));
+
+ struct msghdr hdr;
+ struct iovec iov;
+ unsigned char cmsgbuf[CMSG_SPACE(sizeof(int))];
+ int retcode = -1;
+
+ create_msghdr(&hdr, &iov, &cmsgbuf[0], sizeof(cmsgbuf), &retcode);
- result = sendToServerAncData(SERVICE_SOCKET_OPEN_FOR, send.Pop(), hdr);
+ int result = sendToServerAncData(SERVICE_SOCKET_OPEN_FOR, send.Pop(), hdr);
if (result != SECURITY_SERVER_API_SUCCESS) {
*fd = -1;
return result;
return SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL;
}
- for(cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
+ /*
+ * Since 'socket packet' can handle more than one control message
+ * we need to iterate through all ancillary data elements and check
+ * which one has our file desciptor (SCM_RIGHTS == cmsg->cmsg_type)
+ */
+ for(cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
if((SOL_SOCKET == cmsg->cmsg_level) && (SCM_RIGHTS == cmsg->cmsg_type)) {
memmove(fd, CMSG_DATA(cmsg), sizeof(int));
}
}
return retcode;
- } catch (MessageBuffer::Exception::Base &e) {
- LogDebug("SecurityServer::MessageBuffer::Exception " << e.DumpToString());
- } catch (std::exception &e) {
- LogDebug("STD exception " << e.what());
- } catch (...) {
- LogDebug("Unknown exception occured");
- }
- return SECURITY_SERVER_API_ERROR_UNKNOWN;
+ });
+}
+
+SECURITY_SERVER_API
+int security_server_shared_file_delete(const char *filename)
+{
+ using namespace SecurityServer;
+ return try_catch([&] {
+ if ((NULL == filename || !strlen(filename))) {
+ LogError("Error input param.");
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+ }
+
+ MessageBuffer send;
+
+ Serialization::Serialize(send, (int)OpenForHdrs::DELETE);
+ Serialization::Serialize(send, std::string(filename));
+
+ struct msghdr hdr;
+ struct iovec iov;
+ int retcode = -1;
+
+ create_msghdr(&hdr, &iov, NULL, 0, &retcode);
+
+ int result = sendToServerAncData(SERVICE_SOCKET_OPEN_FOR, send.Pop(), hdr);
+ if (result != SECURITY_SERVER_API_SUCCESS)
+ return result;
+
+ if (hdr.msg_flags & MSG_CTRUNC) {
+ LogError("Not enough space for ancillary element array.");
+ return SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMALL;
+ }
+
+ return retcode;
+ });
}
CHECK_CALLER_APP
};
+enum class OpenForHdrs : unsigned int
+{
+ OPEN,
+ REOPEN,
+ DELETE,
+ OPEN_DEPRECATED
+};
+
extern const size_t COOKIE_SIZE;
enum class PasswordHdrs
#include <security-server-util.h>
const std::string DATA_DIR = "/var/run/security-server";
-const std::string PROHIBITED_STR = "..";
const std::string ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ \
abcdefghijklmnopqrstuvwxyz \
0123456789._-";
}
m_sockSmackLabel = label;
} else
- m_sockSmackLabel = "";
+ m_sockSmackLabel.clear();
return false;
}
}
}
- bool SharedFile::fileExist(const std::string &filename) const
+ bool SharedFile::fileExist(const std::string &filename)
{
std::string filepath = DATA_DIR + "/" + filename;
struct stat buf;
(((buf.st_mode) & S_IFMT) != S_IFLNK));
}
- bool SharedFile::dirExist(const std::string &dirpath) const
+ bool SharedFile::dirExist(const std::string &dirpath)
{
struct stat buf;
(((buf.st_mode) & S_IFMT) == S_IFDIR));
}
- bool SharedFile::deleteDir(const std::string &dirpath) const
+ bool SharedFile::deleteDir(const std::string &dirpath)
{
DIR *dirp;
struct dirent *dp;
return false;
}
- int SharedFile::openFile(const std::string &filename)
+ bool SharedFile::openFile(const std::string &filename, int &fd)
{
- int fd = -1;
std::string filepath = DATA_DIR + "/" + filename;
fd = TEMP_FAILURE_RETRY(open(filepath.c_str(), O_CREAT | O_RDWR, 0600));
int err = errno;
if (-1 == fd) {
LogError("Cannot open file. Error in open(): " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SERVER_ERROR;
+ return true;
}
- return fd;
+ return false;
}
- bool SharedFile::setFileLabel(const std::string &filename, const std::string &label) const
+ bool SharedFile::deleteFile(const std::string &filename)
+ {
+ std::string filepath = DATA_DIR + "/" + filename;
+
+ if (remove(filepath.c_str())) {
+ LogError("Unable to delete file: " << filename.c_str() << " " << strerror(errno));
+ return true;
+ }
+
+ return false;
+ }
+
+ bool SharedFile::setFileLabel(const std::string &filename, const std::string &label)
{
std::string filepath = DATA_DIR + "/" + filename;
bool SharedFile::getFileLabel(const std::string &filename)
{
std::string filepath = DATA_DIR + "/" + filename;
+ char *label = NULL;
if (smack_check()) {
- char *label = NULL;
- if (PC_OPERATION_SUCCESS != smack_getlabel(filepath.c_str(), &label, SMACK_LABEL_ACCESS)) {
+ if (0 != smack_getlabel(filepath.c_str(), &label, SMACK_LABEL_ACCESS)) {
LogError("Unable to get smack label of process.");
return true;
}
+ }
+
+ if (label) {
m_fileSmackLabel = label;
free(label);
} else
return true;
}
- found = filename.find(PROHIBITED_STR);
- if (found != std::string::npos) {
- LogError("Illegal string in filename.");
- return true;
- }
-
return false;
}
+ int SharedFile::openSharedFile(const std::string &filename,
+ const std::string &client_label, int socket, int &fd)
+ {
+ if (checkFileNameSyntax(filename))
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+ if (m_sockCred.getCred(socket))
+ return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED;
+
+ if (fileExist(filename))
+ return SECURITY_SERVER_API_ERROR_FILE_EXIST;
+
+ LogSecureDebug("File: " << filename.c_str() << " does not exist.");
+
+ if (createFile(filename))
+ return SECURITY_SERVER_API_ERROR_FILE_CREATION_FAILED;
+
+ if (setFileLabel(filename, m_sockCred.getLabel()))
+ return SECURITY_SERVER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+
+ if (openFile(filename, fd))
+ return SECURITY_SERVER_API_ERROR_FILE_OPEN_FAILED;
+
+ if (setFileLabel(filename, client_label.c_str()))
+ return SECURITY_SERVER_API_ERROR_SETTING_FILE_LABEL_FAILED;
+
+ return SECURITY_SERVER_API_SUCCESS;
+ }
+
int SharedFile::getFD(const std::string &filename, int socket, int &fd)
{
if (checkFileNameSyntax(filename))
if (setFileLabel(filename, m_sockCred.getLabel()))
return SECURITY_SERVER_API_ERROR_SERVER_ERROR;
- fd = openFile(filename);
+ if (openFile(filename, fd))
+ return SECURITY_SERVER_API_ERROR_FILE_OPEN_FAILED;
if (setFileLabel(filename, m_fileSmackLabel))
return SECURITY_SERVER_API_ERROR_SERVER_ERROR;
return SECURITY_SERVER_API_SUCCESS;
}
+ int SharedFile::reopenSharedFile(const std::string &filename, int socket, int &fd)
+ {
+ if (checkFileNameSyntax(filename))
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+ if (m_sockCred.getCred(socket))
+ return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED;
+
+ if (!fileExist(filename))
+ return SECURITY_SERVER_API_ERROR_FILE_NOT_EXIST;
+
+ if (getFileLabel(filename))
+ return SECURITY_SERVER_API_ERROR_GETTING_FILE_LABEL_FAILED;
+
+ if (m_fileSmackLabel.compare(m_sockCred.getLabel()))
+ return SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED;
+
+ if (openFile(filename, fd))
+ return SECURITY_SERVER_API_ERROR_FILE_OPEN_FAILED;
+
+ return SECURITY_SERVER_API_SUCCESS;
+ }
+
+ int SharedFile::deleteSharedFile(const std::string &filename, int socket)
+ {
+ if (checkFileNameSyntax(filename))
+ return SECURITY_SERVER_API_ERROR_INPUT_PARAM;
+
+ if (m_sockCred.getCred(socket))
+ return SECURITY_SERVER_API_ERROR_GETTING_SOCKET_LABEL_FAILED;
+
+ if (!fileExist(filename))
+ return SECURITY_SERVER_API_ERROR_FILE_NOT_EXIST;
+
+ if (getFileLabel(filename))
+ return SECURITY_SERVER_API_ERROR_GETTING_FILE_LABEL_FAILED;
+
+ if (m_fileSmackLabel.compare(m_sockCred.getLabel()))
+ return SECURITY_SERVER_API_ERROR_AUTHENTICATION_FAILED;
+
+ if (deleteFile(filename))
+ return SECURITY_SERVER_API_ERROR_FILE_DELETION_FAILED;
+
+ return SECURITY_SERVER_API_SUCCESS;
+ }
+
+
} //namespace SecurityServer
public:
SharedFile();
int getFD(const std::string &filename, int socket, int &fd);
+ int openSharedFile(const std::string &filename, const std::string &client_label,
+ int socket, int &fd);
+ int reopenSharedFile(const std::string &filename, int socket, int &fd);
+ int deleteSharedFile(const std::string &filename, int socket);
private:
- bool fileExist(const std::string &filename) const;
- bool dirExist(const std::string &dirpath) const;
- bool deleteDir(const std::string &dirpath) const;
- int openFile(const std::string &filename);
- bool createFile(const std::string &filename);
- bool setFileLabel(const std::string &filename, const std::string &label) const;
+ static bool fileExist(const std::string &filename);
+ static bool dirExist(const std::string &dirpath);
+ static bool deleteDir(const std::string &dirpath);
+ static bool openFile(const std::string &filename, int &fd);
+ static bool createFile(const std::string &filename);
+ static bool deleteFile(const std::string &filename);
+ static bool setFileLabel(const std::string &filename, const std::string &label);
bool getFileLabel(const std::string &filename);
bool checkFileNameSyntax(const std::string &filename) const;
- uid_t m_fileUID;
- gid_t m_fileGID;
- mode_t m_fileMode;
std::string m_fileSmackLabel;
SockCred m_sockCred;
LogDebug("Iteration begin");
std::string filename;
+ std::string client_label;
+ OpenForHdrs msgType;
MessageBuffer sendBuffer;
int retCode = SECURITY_SERVER_API_ERROR_SERVER_ERROR;
return false;
Try {
+ int msgTypeInt;
+ Deserialization::Deserialize(buffer, msgTypeInt); //receive MSG_ID
+ msgType = static_cast<OpenForHdrs>(msgTypeInt);
Deserialization::Deserialize(buffer, filename);
} Catch (MessageBuffer::Exception::Base) {
LogError("Broken protocol. Closing socket.");
return false;
}
- retCode = m_sharedFile.getFD(filename, conn.sock, fd);
+ switch(msgType) {
+ case OpenForHdrs::OPEN:
+ LogDebug("Entering open-for OPEN server handler.");
+ Deserialization::Deserialize(buffer, client_label);
+ retCode = m_sharedFile.openSharedFile(filename, client_label, conn.sock, fd);
+ break;
+ case OpenForHdrs::REOPEN:
+ LogDebug("Entering open-for REOPEN server handler.");
+ retCode = m_sharedFile.reopenSharedFile(filename, conn.sock, fd);
+ break;
+ case OpenForHdrs::DELETE:
+ LogDebug("Entering open-for DELETE server handler.");
+ retCode = m_sharedFile.deleteSharedFile(filename, conn.sock);
+ break;
+ case OpenForHdrs::OPEN_DEPRECATED:
+ LogDebug("Entering open-for OPEN-DEPRECATED server handler.");
+ retCode = m_sharedFile.getFD(filename, conn.sock, fd);
+ default:
+ LogError("Error, unknown function called by client,");
+ break;
+ };
+
if (fd != -1)
descVector.push_back(fd);
SendMsgData sendMsgData(retCode, fd);