xref: /haiku/src/add-ons/network_settings/sshd/SSHServiceAddOn.cpp (revision 97dfeb96704e5dbc5bec32ad7b21379d0125e031)
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 
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 
97 SSHServiceView::~SSHServiceView()
98 {
99 }
100 
101 
102 void
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 
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 
180 SSHServiceItem::~SSHServiceItem()
181 {
182 	if (fView->Parent() == NULL)
183 		delete fView;
184 
185 	delete fItem;
186 }
187 
188 
189 BNetworkSettingsType
190 SSHServiceItem::Type() const
191 {
192 	return B_NETWORK_SETTINGS_TYPE_SERVICE;
193 }
194 
195 
196 BListItem*
197 SSHServiceItem::ListItem()
198 {
199 	return fItem;
200 }
201 
202 
203 BView*
204 SSHServiceItem::View()
205 {
206 	if (fView == NULL)
207 		fView = new SSHServiceView(fSettings);
208 
209 	return fView;
210 }
211 
212 
213 status_t
214 SSHServiceItem::Revert()
215 {
216 	return fView != NULL ? fView->Revert() : B_OK;
217 }
218 
219 
220 bool
221 SSHServiceItem::IsRevertable()
222 {
223 	return fView != NULL ? fView->IsRevertable() : false;
224 }
225 
226 
227 void
228 SSHServiceItem::SettingsUpdated(uint32 which)
229 {
230 	if (fView != NULL)
231 		fView->SettingsUpdated(which);
232 }
233 
234 
235 // #pragma mark -
236 
237 
238 SSHServiceAddOn::SSHServiceAddOn(image_id image,
239 	BNetworkSettings& settings)
240 	:
241 	BNetworkSettingsAddOn(image, settings)
242 {
243 }
244 
245 
246 SSHServiceAddOn::~SSHServiceAddOn()
247 {
248 }
249 
250 
251 BNetworkSettingsItem*
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*
266 instantiate_network_settings_add_on(image_id image, BNetworkSettings& settings)
267 {
268 	return new SSHServiceAddOn(image, settings);
269 }
270