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