Cannot authenticate against Apache DS using C# and LdapConnection? - c#

Problem
I installed and configured a ApacheDS server running ldap. This was a huge step forward for me in teaching myself ldap. However, the following C# console code returns the following error:
System.DirectoryServices.Protocols.LdapException {"The supplied credential is invalid"}
My code is to use this sample code to authenticate a sample user.
Code
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SampleLdapAuthentication
{
class Program
{
static void Main(string[] args)
{
RunLdap run = new RunLdap("localhost", "organization", 635, "hderp", "spaceballs1234");
bool result = run.ValidateCredentials();
if(result)
{
Console.WriteLine("Authentication Succeeded");
}
else
{
Console.WriteLine("Authentication Failed");
}
}
}
}
SampleLdapAuthentication.cs
using System;
using System.Collections.Generic;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace SampleLdapAuthentication
{
public class RunLdap
{
private static string _domainController;
private static string _domain;
private static int _port;
private static string _userName;
private static string _userPassword;
//Constructor. Takes the domain controller, domain, port, username, and password and then calls Ldap Method to run authentication
public RunLdap(string domainController, string domain, int port, string userName, string userPassword)
{
_domainController = domainController;
_domain = null;
_port = port;
_userName = userName;
_userPassword = userPassword;
}
public bool ValidateCredentials()
{
LdapDirectoryIdentifier ldi = new LdapDirectoryIdentifier(_domainController, _port);
NetworkCredential networkCredential = new NetworkCredential(_userName, _userPassword, _domain);
try
{
//We use using so we dispose the object as soon as it goes out of scope
using (LdapConnection connection = new LdapConnection(ldi))
{
//connection.SessionOptions.SecureSocketLayer = true;
connection.AuthType = AuthType.Kerberos;
connection.Bind(networkCredential);
//Not sure what this is doing
}
return true;
}
catch(LdapException ldapException)
{
return false;
}
return false;
}//End of ValidateCredentials
}
}
LDAP Server Details
Notes
The following are worth noting in what I am doing:
I followed this tutorial in creating the server and DIT.
According to my understanding ApacheDS supports keberos out of the box now, so my authentication type should be fine. That is, AuthType
It fails on connection.Bind() method
I am thinking maybe there is something wrong with how I am entering in the credentials and that my C# code is fine. That is why I included the server AD information. I am new to LDAP and using it to authenticate users, so I appreciate your help.

You're not using the distinguished name of the user. When you create your NetworkCredential object, you should be using the distingushed name of the user, in this case, cn=Herp Derp,ou=users,o=organization instead of hderp. The LDAP doesn't know where to look for hderp without the o and ou values.

Related

'IPhoneLine' does not contain a definition for 'PhoneLineStateChenged'

I am just starting with Ozeki VoIP SDK.
in my register method, my phoneLine does not recognize PhoneLineStateChanged.
my code is below.
public void Register(bool registrationRequired,string displayName, string userName, string authenticationId, string registerPassword, string domainHost, string domainPort)
{
try
{
var account = new SIPAccount(registrationRequired, displayName, userName, authenticationId, registerPassword, domainHost, domainPort);
Console.WriteLine("\n Creating SIP account {0}", account);
var natConfiguration = new NatConfiguration(NatTraversalMethod.None);
var phoneLineConfiguration = new PhoneLineConfiguration(account);
//phoneLine = softPhone.CreatePhoneLine(account);
phoneLine = softPhone.CreatePhoneLine(phoneLineConfiguration);
Console.WriteLine("Phoneline created.");
phoneLine.PhoneLineStateChanged += phoneLine_PhoneLineStateChanged;
}
catch
{ }
}
and my references are
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ozeki.Network.Nat;
using Ozeki.VoIP;
using Ozeki.VoIP.SDK;
did I forget a reference or what?
Looking at the SDK examples, it seems that the event is actually called RegistrationStateChanged. So this should work:
phoneLine.RegistrationStateChanged += phoneLine_PhoneLineStateChenged;
It's a little misleading that their example also calls it phoneLine.PhoneLineStateChanged. I guess they renamed it.

Alternate Database Connection in C#

Please someone help me - I have a problem.
I'm trying to code an alternate database for a program I am writing in C#. You see on the website I managed to do it with an if..
This is my php code:
//database connection
$conexion = #mysqli_connect("localhost","todo","todo","dbdaq");
//if mainserver connection is not made then it connects to secondary server
if (!$conexion){
$conexion = mysqli_connect("192.168.0.12","todo","","dbdaq");
}
And that works in PHP, but when I try to write something like that in C#, I can't manage to do it.
Here is my database connection class in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MySql.Data;
using MySql.Data.MySqlClient;
namespace ComunicacionCSharp
{
class ConexionBD
{
public static MySqlConnection ObtenerConexion()
{
MySqlConnection Conectar = new MySqlConnection("Server =localhost; database = dbdaq ; Userid = root; password =");
return Conectar;
}
}
}
NOTE: this class is called from my main GUI interface.
namespace ComunicacionCSharp
{
public partial class Login : Form
{
MySqlConnection conn = ConexionBD.ObtenerConexion();
public string usuario;
public Login()
{
InitializeComponent();
}
}
}
Can someone please help me? I use to have another version of the database connection with an error message if the connection is not found, but I left coding in C# for a while and could not find that piece of code anymore, and I don't remember how to do it :(
mysqli_connect returns a handle to an open connection and in your C# code you pass an unopened connection. You must change a bit your code, something like this:
public static MySqlConnection ObtenerConexion()
{
MySqlConnection Conectar = null;
try
{
Conectar = new MySqlConnection(yourFirstConnectionString);
Conectar.Open();
}
catch
{
try
{
Conectar = new MySqlConnection(yourSecondConnectionString);
Conectar.Open();
}
catch{ }
}
return Conectar;
}
Remember to check the connection wherever you use it, if both connections fail it will return null.

How to Generate Text File from API Source?

I have a small problem. I just recently started using Twilio's API to generate a record of messages that was sent to my assigned SID and Auth Token. However my question is how can I generate a text file, based off of what the console writes from the source its addressed to?
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using Twilio;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Find your Account Sid and Auth Token at twilio.com/user/account
string AccountSid = "X";
string AuthToken = "X";
var twilio = new TwilioRestClient(AccountSid, AuthToken);
// Build the parameters
var options = new MessageListRequest();
options.From = "2015-07-01";
options.To = "2015-07-13";
var messages = twilio.ListMessages(options);
foreach (var message in messages.Messages)
{
Console.WriteLine(message.Body);
Console.Read();
}
}
}
}
Writing to a text file is pretty much boilerplate. The methods are shown here:
https://msdn.microsoft.com/en-us/library/8bh11f1k.aspx

400 Bad Request (Invalid Host) using simple webserver in C#

I've got a small C# console app to work as a webserver. It responds well on the NAT with devices in the same network, but when I try to access it in a browser from the external IP i get a 400.
The router is configured to port forward, otherwise I get a 404.
localhost:8888/test works fine.
also 192.168.0.x:8888/test for any device.
xxx.xxx.xxx.xxx:8888/test fails with HTTP Error 400. The request hostname is invalid.
Any suggestions?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace httpsrv
{
class Program
{
static void Main(string[] args)
{
WebServer ws = new WebServer(SendResponse, "http://localhost:8888/test/");
ws.Run();
Console.WriteLine("Pi server started");
Console.ReadKey();
ws.Stop();
}
public static string SendResponse(HttpListenerRequest request)
{
return string.Format("<HTML><BODY>Hosted from rasp. pi!<br>{0}</BODY></HTML>", DateTime.Now);
}
}
}
Webserver class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace httpsrv
{
public class WebServer
{
private readonly HttpListener _listener = new HttpListener();
private readonly Func<HttpListenerRequest, string> _responderMethod;
public WebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
{
if (!HttpListener.IsSupported)
throw new NotSupportedException(
"Needs Windows XP SP2, Server 2003 or later.");
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
if (method == null)
throw new ArgumentException("method");
foreach (string s in prefixes)
_listener.Prefixes.Add(s);
_responderMethod = method;
_listener.Start();
}
public WebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
: this(prefixes, method) { }
public void Run()
{
ThreadPool.QueueUserWorkItem((o) =>
{
Console.WriteLine("Webserver running...");
try
{
while (_listener.IsListening)
{
ThreadPool.QueueUserWorkItem((c) =>
{
var ctx = c as HttpListenerContext;
try
{
string rstr = _responderMethod(ctx.Request);
byte[] buf = Encoding.UTF8.GetBytes(rstr);
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
catch { }
finally
{
ctx.Response.OutputStream.Close();
}
}, _listener.GetContext());
}
}
catch { }
});
}
public void Stop()
{
_listener.Stop();
_listener.Close();
}
}
}
I had this issue on ubuntu when using self hosted OWIN and c#.
I fixed it by setting the base address set inside my .exe to
http://*:80
instead of
http://192.168.1.1:80
This
WebServer ws = new WebServer(SendResponse, "http://*:80/");
plus starting application (or command prompt / Visual Studio) with 'Run as administrator' mode worked great!
Either your DNS or name resolution is bad.
There are no routes to forward that traffic to your web server
Check your port forwarding you should be forwarding port 8888 to the internal IP
Last but not least check your firewall, it should allow port 8888
Looking at your code, it seems you are hard coding the request, make that a variable so that you can change it on the fly
Had similar issue as #sean-bradley - but on .net.
This worked great:
WebServer ws = new WebServer(SendResponse, "http://+:80/");

DirectoryEntry to change password: Different behavior between Vista/Server2008

On a Vista dev machine I used this code successfully to change user "Administrator" password:
directoryEntry.Invoke("SetPassword", "new");
When I moved it over to my Server 2008 dev machine that code did not work, and I was forced to use the following code:
directoryEntry.Invoke("ChangePassword", new object[] { "old", "new" });
My question is, why?
For both cases, I created my DirectoryEntry object as such:
DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1}", computerName, username));
Thanks! 8)
In case you guys find it helpful, heres the actual code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.DirectoryServices;
using System.Security.Principal;
namespace AccountMod
{
class Program
{
static void Main()
{
Console.WriteLine("Attempting reset...\n");
try
{
String machineNameAndUser = WindowsIdentity.GetCurrent().Name.ToString();
String machineName = WindowsIdentity.GetCurrent().Name.ToString().Substring(0, machineNameAndUser.IndexOf('\\'));
Console.WriteLine("Computer's name: " + machineName);
ResetPassword(machineName, "Administrator", "new");
//ChangePassword("Administrator", "current", "new"); Console.WriteLine("Finished...");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.InnerException);
}
Console.ReadKey();
}
public static void ResetPassword(string computerName, string username, string newPassword)
{
DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1}", computerName, username));
directoryEntry.Invoke("SetPassword", newPassword);
//directoryEntry.Invoke("ChangePassword", new object[] { "current", "new" });
}
}
}
Are you (or could you upgrade to) .NET 3.5? The AD integration for users, groups, computers has been massively improved in .NET 3.5 - check out the MSDN article Managing Directory Security Principals in the .NET Framework 3.5 for details.
In your case, you could do something like:
// establish context for local machine
PrincipalContext ctx = new PrincipalContext(ContextType.Machine);
// find the "Administrator" account
UserPrincipal admin = UserPrincipal.FindByIdentity(ctx, "Administrator");
// set the password to a new value
admin.SetPassword("new-top-secret-password");
admin.Save();
and you're done! The WinNT: provider is very limited in what it can do and should be avoided if ever possible.
Check user properties for which you want to set password, if
user cannot change password
property is checked then u cant set password by using directoryEntry.Invoke("SetPassword", "new");Use admin credential while creating DirectoryEntry object or uncheck " user cannot change password" property

Categories

Resources