1 /*
2 * Copyright 2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Axel Dörfler, <axeld@pinc-software.de>
7 * Ingo Weinhold <ingo_weinhold@gmx.de>
8 */
9
10
11 #include <pwd.h>
12
13 #include <Button.h>
14 #include <Catalog.h>
15 #include <LayoutBuilder.h>
16 #include <NetworkSettings.h>
17 #include <NetworkSettingsAddOn.h>
18 #include <StringView.h>
19 #include <TextView.h>
20
21 #include <NetServer.h>
22 #include <RegistrarDefs.h>
23 #include <user_group.h>
24 #include <util/KMessage.h>
25
26 #include "ServiceListItem.h"
27 #include "ServiceView.h"
28
29
30 using namespace BNetworkKit;
31
32
33 #undef B_TRANSLATION_CONTEXT
34 #define B_TRANSLATION_CONTEXT "SSHServiceAddOn"
35
36
37 static const uint32 kMsgToggleService = 'tgls';
38
39
40 class SSHServiceAddOn : public BNetworkSettingsAddOn {
41 public:
42 SSHServiceAddOn(image_id image,
43 BNetworkSettings& settings);
44 virtual ~SSHServiceAddOn();
45
46 virtual BNetworkSettingsItem*
47 CreateNextItem(uint32& cookie);
48 };
49
50
51 class SSHServiceView : public ServiceView {
52 public:
53 SSHServiceView(BNetworkSettings& settings);
54 virtual ~SSHServiceView();
55
56 protected:
57 virtual void Enable();
58 };
59
60
61 class SSHServiceItem : public BNetworkSettingsItem {
62 public:
63 SSHServiceItem(BNetworkSettings& settings);
64 virtual ~SSHServiceItem();
65
66 virtual BNetworkSettingsType
67 Type() const;
68
69 virtual BListItem* ListItem();
70 virtual BView* View();
71
72 virtual status_t Revert();
73 virtual bool IsRevertable();
74
75 virtual void SettingsUpdated(uint32 which);
76
77 private:
78 BNetworkSettings& fSettings;
79 BListItem* fItem;
80 ServiceView* fView;
81 };
82
83
84 // #pragma mark -
85
86
SSHServiceView(BNetworkSettings & settings)87 SSHServiceView::SSHServiceView(BNetworkSettings& settings)
88 :
89 ServiceView("ssh", NULL, B_TRANSLATE("SSH server"), B_TRANSLATE(
90 "The SSH server allows you to "
91 "remotely access your machine with a terminal session, as well as "
92 "file access using the SCP and SFTP protocols."), settings)
93 {
94 }
95
96
~SSHServiceView()97 SSHServiceView::~SSHServiceView()
98 {
99 }
100
101
102 void
Enable()103 SSHServiceView::Enable()
104 {
105 if (getpwnam("sshd") == NULL) {
106 // We need to create a dedicated user for the service
107 // The following code is copied from useradd, and should be moved
108 // to a public class.
109 gid_t groupID = 100;
110
111 // Find an unused user ID
112 uid_t userID = 1000;
113 while (getpwuid(userID) != NULL)
114 userID++;
115
116 const char* home = "/boot/home";
117 int expiration = 99999;
118 int inactive = -1;
119 const char* shell = "/bin/sh";
120 const char* realName = "";
121
122 int min = -1;
123 int max = -1;
124 int warn = 7;
125
126 // prepare request for the registrar
127 KMessage message(BPrivate::B_REG_UPDATE_USER);
128 if (message.AddInt32("uid", userID) == B_OK
129 && message.AddInt32("gid", groupID) == B_OK
130 && message.AddString("name", "sshd") == B_OK
131 && message.AddString("password", "x") == B_OK
132 && message.AddString("home", home) == B_OK
133 && message.AddString("shell", shell) == B_OK
134 && message.AddString("real name", realName) == B_OK
135 && message.AddString("shadow password", "!") == B_OK
136 && message.AddInt32("last changed", time(NULL)) == B_OK
137 && message.AddInt32("min", min) == B_OK
138 && message.AddInt32("max", max) == B_OK
139 && message.AddInt32("warn", warn) == B_OK
140 && message.AddInt32("inactive", inactive) == B_OK
141 && message.AddInt32("expiration", expiration) == B_OK
142 && message.AddInt32("flags", 0) == B_OK
143 && message.AddBool("add user", true) == B_OK) {
144 // send the request
145 KMessage reply;
146 status_t error = send_authentication_request_to_registrar(message,
147 reply);
148 if (error != B_OK) {
149 fprintf(stderr, "Error: Failed to create user: %s\n",
150 strerror(error));
151 }
152 }
153 }
154
155 BNetworkServiceSettings settings;
156 settings.SetName("ssh");
157 settings.SetStandAlone(true);
158
159 settings.AddArgument("/bin/sshd");
160 settings.AddArgument("-D");
161
162 BMessage service;
163 if (settings.GetMessage(service) == B_OK)
164 fSettings.AddService(service);
165 }
166
167
168 // #pragma mark -
169
170
SSHServiceItem(BNetworkSettings & settings)171 SSHServiceItem::SSHServiceItem(BNetworkSettings& settings)
172 :
173 fSettings(settings),
174 fItem(new ServiceListItem("ssh", B_TRANSLATE("SSH server"), settings)),
175 fView(NULL)
176 {
177 }
178
179
~SSHServiceItem()180 SSHServiceItem::~SSHServiceItem()
181 {
182 if (fView->Parent() == NULL)
183 delete fView;
184
185 delete fItem;
186 }
187
188
189 BNetworkSettingsType
Type() const190 SSHServiceItem::Type() const
191 {
192 return B_NETWORK_SETTINGS_TYPE_SERVICE;
193 }
194
195
196 BListItem*
ListItem()197 SSHServiceItem::ListItem()
198 {
199 return fItem;
200 }
201
202
203 BView*
View()204 SSHServiceItem::View()
205 {
206 if (fView == NULL)
207 fView = new SSHServiceView(fSettings);
208
209 return fView;
210 }
211
212
213 status_t
Revert()214 SSHServiceItem::Revert()
215 {
216 return fView != NULL ? fView->Revert() : B_OK;
217 }
218
219
220 bool
IsRevertable()221 SSHServiceItem::IsRevertable()
222 {
223 return fView != NULL ? fView->IsRevertable() : false;
224 }
225
226
227 void
SettingsUpdated(uint32 which)228 SSHServiceItem::SettingsUpdated(uint32 which)
229 {
230 if (fView != NULL)
231 fView->SettingsUpdated(which);
232 }
233
234
235 // #pragma mark -
236
237
SSHServiceAddOn(image_id image,BNetworkSettings & settings)238 SSHServiceAddOn::SSHServiceAddOn(image_id image,
239 BNetworkSettings& settings)
240 :
241 BNetworkSettingsAddOn(image, settings)
242 {
243 }
244
245
~SSHServiceAddOn()246 SSHServiceAddOn::~SSHServiceAddOn()
247 {
248 }
249
250
251 BNetworkSettingsItem*
CreateNextItem(uint32 & cookie)252 SSHServiceAddOn::CreateNextItem(uint32& cookie)
253 {
254 if (cookie++ == 0)
255 return new SSHServiceItem(Settings());
256
257 return NULL;
258 }
259
260
261 // #pragma mark -
262
263
264 extern "C"
265 BNetworkSettingsAddOn*
instantiate_network_settings_add_on(image_id image,BNetworkSettings & settings)266 instantiate_network_settings_add_on(image_id image, BNetworkSettings& settings)
267 {
268 return new SSHServiceAddOn(image, settings);
269 }
270