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
|
// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef _WIN32
#include <sys/socket.h>
#include "../include/credentials.hpp"
#include <vsomeip/internal/logger.hpp>
#ifdef ANDROID
#include "../../configuration/include/internal_android.hpp"
#else
#include "../../configuration/include/internal.hpp"
#endif
namespace vsomeip_v3 {
void credentials::activate_credentials(const int _fd) {
int optval = 1;
if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
VSOMEIP_ERROR << "vSomeIP Security: Activating socket option for receiving "
<< "credentials failed.";
}
}
void credentials::deactivate_credentials(const int _fd) {
int optval = 0;
if (setsockopt(_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
VSOMEIP_ERROR << "vSomeIP Security: Deactivating socket option for receiving "
<< "credentials failed.";
}
}
client_t credentials::receive_credentials(const int _fd, uid_t& _uid, gid_t& _gid) {
struct ucred *ucredp;
struct msghdr msgh;
struct iovec iov;
union {
struct cmsghdr cmh;
char control[CMSG_SPACE(sizeof(struct ucred))];
} control_un;
struct cmsghdr *cmhp;
// Sender client_id will be received as data
client_t client = VSOMEIP_ROUTING_CLIENT;
// Set 'control_un' to describe ancillary data that we want to receive
control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred));
control_un.cmh.cmsg_level = SOL_SOCKET;
control_un.cmh.cmsg_type = SCM_CREDENTIALS;
// Set 'msgh' fields to describe 'control_un'
msgh.msg_control = control_un.control;
msgh.msg_controllen = sizeof(control_un.control);
// Set fields of 'msgh' to point to buffer used to receive (real) data read by recvmsg()
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
iov.iov_base = &client;
iov.iov_len = sizeof(client_t);
// We don't need address of peer as we using connect
msgh.msg_name = NULL;
msgh.msg_namelen = 0;
// Receive client_id plus ancillary data
ssize_t nr = recvmsg(_fd, &msgh, 0);
if (nr == -1) {
VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. No data.";
}
cmhp = CMSG_FIRSTHDR(&msgh);
if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))
|| cmhp->cmsg_level != SOL_SOCKET || cmhp->cmsg_type != SCM_CREDENTIALS) {
VSOMEIP_ERROR << "vSomeIP Security: Receiving credentials failed. Invalid data.";
} else {
ucredp = (struct ucred *) CMSG_DATA(cmhp);
_uid = ucredp->uid;
_gid = ucredp->gid;
}
return client;
}
void credentials::send_credentials(const int _fd, client_t _client) {
struct msghdr msgh;
struct iovec iov;
// data to send
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
iov.iov_base = &_client;
iov.iov_len = sizeof(client_t);
// destination not needed as we use connect
msgh.msg_name = NULL;
msgh.msg_namelen = 0;
// credentials not need to set explicitly
msgh.msg_control = NULL;
msgh.msg_controllen = 0;
// send client id with credentials
ssize_t ns = sendmsg(_fd, &msgh, 0);
if (ns == -1) {
VSOMEIP_ERROR << "Sending credentials failed.";
}
}
} // namespace vsomeip_v3
#endif // #ifndef _WIN32
|