summaryrefslogtreecommitdiff
path: root/implementation/endpoints/src/credentials.cpp
blob: 3b9762c8be32c737a327e4f29a3e960945721edc (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
// 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